singrdk/base/Services/NetStack/Runtime/TcpSessionPool.cs

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
}
}
}
}