private static bool IsRWEntryEmpty(ReaderWriterCount rwc) { if (rwc.ThreadId == -1) { return(true); } if (rwc.ReaderCount == 0 && rwc.Rc == null) { return(true); } if (rwc.ReaderCount == 0 && rwc.Rc.WriterCount == 0 && rwc.Rc.UpgradeCount == 0) { return(true); } return(false); }
/// <summary> /// This routine retrieves/sets the per-thread counts needed to enforce the /// various rules related to acquiring the lock. It's a simple hash table, /// where the first entry is pre-allocated for optimizing the common case. /// After the first element has been allocated, duplicates are kept of in /// linked-list. The entries are never freed, and the max size of the /// table would be bounded by the max number of threads that held the lock /// simultaneously. /// /// DontAllocate is set to true if the caller just wants to get an existing /// entry for this thread, but doesn't want to add one if an existing one /// could not be found. /// </summary> private ReaderWriterCount GetThreadRWCount(int id, bool dontAllocate) { int hash = id & HashTableSize; ReaderWriterCount firstfound = null; #if DEBUG Debug.Assert(MyLockHeld); #endif if (null == _rwc[hash]) { if (dontAllocate) { return(null); } _rwc[hash] = new ReaderWriterCount(_isReentrant); } if (_rwc[hash].ThreadId == id) { return(_rwc[hash]); } if (IsRWEntryEmpty(_rwc[hash]) && !dontAllocate) { //No more entries in chain, so no more searching required. if (_rwc[hash].Next == null) { _rwc[hash].ThreadId = id; return(_rwc[hash]); } firstfound = _rwc[hash]; } //SlowPath var temp = _rwc[hash].Next; while (temp != null) { if (temp.ThreadId == id) { return(temp); } if (firstfound == null) { if (IsRWEntryEmpty(temp)) { firstfound = temp; } } temp = temp.Next; } if (dontAllocate) { return(null); } if (firstfound == null) { temp = new ReaderWriterCount(_isReentrant) { ThreadId = id, Next = _rwc[hash].Next }; _rwc[hash].Next = temp; return(temp); } firstfound.ThreadId = id; return(firstfound); }
private static bool IsRwHashEntryChanged(ReaderWriterCount lrwc, int id) { return(lrwc.ThreadId != id); }