85 lines
3.3 KiB
C#
85 lines
3.3 KiB
C#
// ----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Collections;
|
|
|
|
namespace NetStack.Runtime
|
|
{
|
|
/// <summary>
|
|
/// Static class maintains a pool of Tcp Sessions kept as a FILO (Stack).
|
|
/// </summary>
|
|
public static class TcpSessionPool
|
|
{
|
|
// Session Recycle to GC ratio as a Rational Approximation.
|
|
// BUGBUG: When 992 and 1024 fixed, set to UInt64.Max or remove
|
|
private const long SessionRecycleToGCRANumerator = 1ul;
|
|
private const long SessionRecycleToGCRADenominator = 256ul;
|
|
private static long rationalApproximationCurrentValue =
|
|
TcpSessionPool.SessionRecycleToGCRADenominator / -2;
|
|
|
|
static TcpModule tcpModule;
|
|
static Stack tcpSessions = new Stack();
|
|
|
|
static ulong getCalls = 0;
|
|
static ulong allocations = 0;
|
|
static ulong recycleCalls = 0;
|
|
|
|
public static void SetTcpModule(TcpModule tcpModule)
|
|
{
|
|
TcpSessionPool.tcpModule = tcpModule;
|
|
}
|
|
|
|
public static TcpSession! Get()
|
|
{
|
|
TcpSession! tcpSession;
|
|
lock (TcpSessionPool.tcpSessions) {
|
|
TcpSessionPool.getCalls++;
|
|
|
|
if(tcpSessions.Count <= 0) {
|
|
TcpSessionPool.allocations++;
|
|
tcpSession = new TcpSession(tcpModule);
|
|
}
|
|
else {
|
|
tcpSession = (TcpSession!) tcpSessions.Pop();
|
|
assert(tcpSession.IsClosed);
|
|
Core.Instance().DeregisterSession(tcpSession.Protocol, tcpSession);
|
|
tcpSession =
|
|
TcpSessionPool.tcpModule.ReInitializeSession(tcpSession);
|
|
}
|
|
}
|
|
|
|
return tcpSession;
|
|
}
|
|
|
|
public static void Recycle(TcpSession! tcpSession)
|
|
{
|
|
assert(tcpSession.IsClosed);
|
|
|
|
// Under Exclusion, count call and add to (free) list.
|
|
lock (TcpSessionPool.tcpSessions) {
|
|
TcpSessionPool.recycleCalls++;
|
|
tcpSessions.Push(tcpSession);
|
|
// TODO: Occasionally (1/1024 times?) free a session to
|
|
// lower usage from highwater mark to high average at the
|
|
// cost of some additional Alloc/Free cycles.
|
|
}
|
|
|
|
// Run the CG every N/D session recycles to avoid Bugs 992 and 1024.
|
|
// Can be done after every session if searching for memory leaks.
|
|
TcpSessionPool.rationalApproximationCurrentValue +=
|
|
TcpSessionPool.SessionRecycleToGCRANumerator;
|
|
while (TcpSessionPool.rationalApproximationCurrentValue > 0) {
|
|
TcpSessionPool.rationalApproximationCurrentValue -=
|
|
TcpSessionPool.SessionRecycleToGCRADenominator;
|
|
GC.Collect(); // Free memory and fill finalizer Q.
|
|
GC.WaitForPendingFinalizers(); // Dispose non-managed stuff
|
|
GC.Collect(); // Free memory release by finalizing
|
|
}
|
|
}
|
|
}
|
|
}
|