// Allocate a native delegate record for "del". The caller must hold // the CriticalSection. private static int AllocateNativeDelegateRecord(Delegate del) { int idx; int table; int offset; DebugPrint("AllocateNativeDelegateRecord (list={0}, extent {1})\n", __arglist(FreeListStartIdx, FreeExtentStartIdx)); if (FreeListStartIdx != FREE_LIST_EMPTY) { // There's space in the free list: use that int nextFreeIdx; idx = FreeListStartIdx; SplitIdx(idx, out table, out offset); nextFreeIdx = NativeDelegateTable[table][offset].NextIdx(); FreeListStartIdx = nextFreeIdx; } else { // There's no space in the free list, use the next slot in the // free extent. idx = FreeExtentStartIdx; SplitIdx(idx, out table, out offset); FreeExtentStartIdx++; if (offset + 1 == NativeDelegateTable[table].Length) { // We've used the last slot in the free extent: allocate some // more. int currentLength = NativeDelegateTable[table].Length; int nextLength = currentLength * 2; DebugPrint("AllocateNativeDelegateRecord expanding to {0} len {1}\n", __arglist(table + 1, nextLength)); NativeDelegateTable[table + 1] = new NativeDelegateRecord[nextLength]; } } NativeDelegateTable[table][offset].Allocate(del); DebugPrint("AllocateNativeDelegateRecord got {0} (list={1}, extent {2})\n", __arglist(idx, FreeListStartIdx, FreeExtentStartIdx)); return(idx); }
static Delegate() { CriticalSection = new Mutex(); NativeDelegateTable = new NativeDelegateRecord[24][]; NativeDelegateTable[0] = new NativeDelegateRecord[FIRST_TABLE_SIZE]; FreeExtentStartIdx = 0; FreeListStartIdx = FREE_LIST_EMPTY; #if FALSE // Enable this code to force testing of the FreeNativeDelegateRecord fn for (int i = 0; i < FIRST_TABLE_SIZE * 2; i++) { int idx = AllocateNativeDelegateRecord(CriticalSection); VTable.Assert(idx == i); } for (int i = 0; i < FIRST_TABLE_SIZE * 2; i++) { FreeNativeDelegateRecord(i); } #endif }