public void Write <T>(T[] instances, Action <T> write) { RMonitor.Enter(_writersMutex); try { var index = RInterlocked.Read(ref _index); var nextIndex = Toggle(index); if (WaitOnFirstWrite) { WaitWhileOccupied(_readIndicator[nextIndex]); // Now we're subject to starvation by (new) readers. } // And mutual exclusion may still be violated. _snoop.BeginWrite(nextIndex); write(instances[nextIndex]); _snoop.EndWrite(nextIndex); // Move subsequent readers to 'next' instance RInterlocked.Exchange(ref _index, nextIndex); // Wait for all readers to finish reading the instance we want to write next WaitWhileOccupied(_readIndicator[index]); // At this point there may be readers, but they must be on nextReadIndex, we can // safely write. _snoop.BeginWrite(index); write(instances[index]); _snoop.EndWrite(index); } finally { RMonitor.Exit(_writersMutex); } }
private void PulsingThread(int numPulses) { for (int i = 0; i < numPulses; ++i) { RMonitor.Enter(_lockObject); RMonitor.Pulse(_lockObject); RMonitor.Exit(_lockObject); } }
private void LockingThread(int idx) { var myLock = ActiveConfig.LockObjects[idx]; var nextLock = ActiveConfig.LockObjects[(idx + 1) % ActiveConfig.NumThreads]; RMonitor.Enter(myLock); RMonitor.Enter(nextLock); RMonitor.Exit(nextLock); RMonitor.Exit(myLock); }
private void EnterSlow() { RMonitor.Enter(_lockObj); RUnordered.Write(ref _holdingThreadId, Environment.CurrentManagedThreadId); RInterlocked.MemoryBarrierProcessWide(); while (RUnordered.Read(ref _isHeld) == 1) { RE.Yield(); } RUnordered.Write(ref _isHeld, 1); RMonitor.Exit(_lockObj); return; }
internal void EnterReadLock() { var idx = GetReaderIndex(); RUnordered.Write(ref _readIndicator[idx], 1); if (RUnordered.Read(ref _writerActive) == 1) { RUnordered.Write(ref _readIndicator[idx], 0); RMonitor.Enter(_lockObj); RUnordered.Write(ref _readIndicator[idx], 1); RMonitor.Exit(_lockObj); } _snoop.BeginRead(); }
private LockCookie EnterSlow() { RMonitor.Enter(_lockObj); var oldEntry = RUnordered.Read(ref _current); RUnordered.Write(ref _current, new LockCookie(Environment.CurrentManagedThreadId)); RInterlocked.MemoryBarrierProcessWide(); while (oldEntry != null && RUnordered.Read(ref oldEntry.Taken) == 1) { RE.Yield(); } var current = RUnordered.Read(ref _current); RUnordered.Write(ref current.Taken, 1); RMonitor.Exit(_lockObj); return(current); }
public void Write <T>(T[] instances, Action <T> write) { RMonitor.Enter(_writersMutex); try { // var readIndex = RUnordered.Read(ref _readIndex); var readIndex = RInterlocked.Read(ref _readIndex); var nextReadIndex = Toggle(readIndex); _snoop.BeginWrite(nextReadIndex); write(instances[nextReadIndex]); _snoop.EndWrite(nextReadIndex); // Move subsequent readers to 'next' instance RInterlocked.Exchange(ref _readIndex, nextReadIndex); // Wait for all readers marked in the 'next' read indicator, // these readers could be reading the 'readIndex' instance // we want to write next var versionIndex = RInterlocked.Read(ref _versionIndex); //var versionIndex = RUnordered.Read(ref _versionIndex); var nextVersionIndex = Toggle(versionIndex); WaitWhileOccupied(_readIndicator[nextVersionIndex]); // Move subsequent readers to the 'next' read indicator RInterlocked.Exchange(ref _versionIndex, nextVersionIndex); // RUnordered.Write(ref _versionIndex, nextVersionIndex); // At this point all subsequent readers will read the 'next' instance // and mark the 'nextVersionIndex' read indicator, so the only remaining potential // readers are the ones on the 'versionIndex' read indicator, so wait for them to finish WaitWhileOccupied(_readIndicator[versionIndex]); // At this point there may be readers, but they must be on nextReadIndex, we can // safely write. _snoop.BeginWrite(readIndex); write(instances[readIndex]); _snoop.EndWrite(readIndex); } finally { RMonitor.Exit(_writersMutex); } }
public void Write <T>(T[] instances, Action <T> write) { RMonitor.Enter(_writersMutex); try { var readIndex = RInterlocked.Read(ref _readIndex); var nextReadIndex = Toggle(readIndex); _snoop.BeginWrite(nextReadIndex); write(instances[nextReadIndex]); _snoop.EndWrite(nextReadIndex); RInterlocked.Exchange(ref _readIndex, nextReadIndex); WaitWhileOccupied(_readIndicator); _snoop.BeginWrite(readIndex); write(instances[readIndex]); _snoop.EndWrite(readIndex); } finally { RMonitor.Exit(_writersMutex); } }
internal void ExitWriteLock() { RUnordered.Write(ref _writerActive, 0); _snoop.EndWrite(); RMonitor.Exit(_lockObj); }
public void WaitingThread() { RMonitor.Enter(_lockObject); RMonitor.Wait(_lockObject); RMonitor.Exit(_lockObject); }