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