// ---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // ---------------------------------------------------------------------------- using System; using System.Collections; namespace NetStack.Runtime { /// /// Static class maintains a pool of Tcp Sessions kept as a FILO (Stack). /// 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 } } } }