public UncheckedReaderWriterLock() { this.sentinelToken = new WaitingToken(); this.innerLock = new LightweightSpinLock(); this.id = Interlocked.Increment(ref counter); this.readerCount = 0; this.writerPending = 0; }
public void EnterWrite() { // Indicate that a writer operation entered Interlocked.CompareExchange(ref this.writerPending, 1, 0); // Allocate wait token WaitingToken wait = this.AllocateWaitingToken(); this.WaitForWrite(wait); }
private void WaitForWrite(WaitingToken wait) { int retry = 0; while (true) { // Check if out token is the next and all readers has left if (Interlocked.CompareExchange(ref this.sentinelToken.Next, wait, wait) == wait && Interlocked.CompareExchange(ref this.readerCount, 0, 0) == 0) { return; } LightweightSpinLock.SpinWait(ref retry); } }
private void DropWaitingToken() { this.innerLock.Enter(); // sentinelToken.next = current token (it should not be null) WaitingToken next = this.sentinelToken.Next.Next; this.sentinelToken.Next = next; if (next == null) { // Indicat that no operation wants to write anymore Interlocked.CompareExchange(ref this.writerPending, 0, 1); } this.innerLock.Exit(); }
private WaitingToken AllocateWaitingToken() { WaitingToken wait = new WaitingToken(); this.innerLock.Enter(); // Find the last token WaitingToken last = this.sentinelToken; while (last.Next != null) { last = last.Next; } // Concat to the end last.Next = wait; this.innerLock.Exit(); return(wait); }
private WaitingToken AllocateWaitingToken() { WaitingToken wait = new WaitingToken(); this.innerLock.Enter(); // Find the last token WaitingToken last = this.sentinelToken; while (last.Next != null) { last = last.Next; } // Concat to the end last.Next = wait; this.innerLock.Exit(); return wait; }