Example #1
0
            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);
                }
            }
Example #2
0
            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);
     }
 }