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 int GetReaderIndex() { if (_thisReaderIndex.IsValueCreated) { return(_thisReaderIndex.Value); } var result = RInterlocked.Increment(ref _nextReaderIndex) - 1; _thisReaderIndex.Value = result; return(result); }
internal void EnterWriteLock() { RMonitor.Enter(_lockObj); RUnordered.Write(ref _writerActive, 1); RInterlocked.MemoryBarrierProcessWide(); while (ReadInProgress()) { RE.Yield(); } _snoop.BeginWrite(); return; }
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; }
public void Add(int v) { while (true) { var local = RVolatile.Read(ref _data); var copy = local == null ? new List <int>() : new List <int>(local); copy.Add(v); if (RInterlocked.CompareExchange(ref _data, copy, local)) { break; } } }
public U Read <T, U>(T[] instances, Func <T, U> read) { _readIndicator.Arrive(); try { var idx = RInterlocked.Read(ref _readIndex); _snoop.BeginRead(idx); var result = read(instances[idx]); _snoop.EndRead(idx); return(result); } finally { _readIndicator.Depart(); } }
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); } }
public void Depart() { RInterlocked.Decrement(ref _numReaders); }
public void Arrive() { RInterlocked.Increment(ref _numReaders); }
public void Depart() { int index = GetIndex(); RInterlocked.Decrement(ref _occupancyCounts[index]); }
public void Arrive() { int index = GetIndex(); RInterlocked.Increment(ref _occupancyCounts[index]); }