private static ThreadLocalLockEntry GetOrCreateCurrentSlow(long lockID, ThreadLocalLockEntry headEntry) { Debug.Assert(lockID != 0); Debug.Assert(headEntry == t_lockEntryHead); Debug.Assert(headEntry == null || headEntry._lockID != lockID); ThreadLocalLockEntry entry = null; ThreadLocalLockEntry emptyEntryPrevious = null; ThreadLocalLockEntry emptyEntry = null; if (headEntry != null) { if (headEntry.IsFree) { emptyEntry = headEntry; } for (ThreadLocalLockEntry previousEntry = headEntry, currentEntry = headEntry._next; currentEntry != null; previousEntry = currentEntry, currentEntry = currentEntry._next) { if (currentEntry._lockID == lockID) { VerifyNoNonemptyEntryInListAfter(lockID, currentEntry); // Unlink the entry, preparing to move it to the head of the list previousEntry._next = currentEntry._next; entry = currentEntry; break; } if (emptyEntry == null && currentEntry.IsFree) { // Record the first empty entry in case there is no existing entry emptyEntryPrevious = previousEntry; emptyEntry = currentEntry; } } } if (entry == null) { if (emptyEntry != null) { // Claim the first empty entry that was found emptyEntry._lockID = lockID; // Unlink the empty entry, preparing to move it to the head of the list if (emptyEntryPrevious == null) { Debug.Assert(emptyEntry == headEntry); return emptyEntry; } emptyEntryPrevious._next = emptyEntry._next; entry = emptyEntry; } else { entry = new ThreadLocalLockEntry(lockID); } } // Insert the entry at the head of the list Debug.Assert(entry._lockID == lockID); entry._next = headEntry; t_lockEntryHead = entry; return entry; }
private static void VerifyNoNonemptyEntryInListAfter(long lockID, ThreadLocalLockEntry afterEntry) { Debug.Assert(lockID != 0); Debug.Assert(afterEntry != null); for (ThreadLocalLockEntry currentEntry = afterEntry._next; currentEntry != null; currentEntry = currentEntry._next) { Debug.Assert(currentEntry._lockID != lockID || currentEntry.IsFree); } }