Beispiel #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);
                }
            }
Beispiel #2
0
            private int GetReaderIndex()
            {
                if (_thisReaderIndex.IsValueCreated)
                {
                    return(_thisReaderIndex.Value);
                }
                var result = RInterlocked.Increment(ref _nextReaderIndex) - 1;

                _thisReaderIndex.Value = result;
                return(result);
            }
Beispiel #3
0
 internal void EnterWriteLock()
 {
     RMonitor.Enter(_lockObj);
     RUnordered.Write(ref _writerActive, 1);
     RInterlocked.MemoryBarrierProcessWide();
     while (ReadInProgress())
     {
         RE.Yield();
     }
     _snoop.BeginWrite();
     return;
 }
Beispiel #4
0
 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;
 }
Beispiel #5
0
 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();
     }
 }
Beispiel #7
0
            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);
            }
Beispiel #8
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);
     }
 }
Beispiel #10
0
 public void Depart()
 {
     RInterlocked.Decrement(ref _numReaders);
 }
Beispiel #11
0
 public void Arrive()
 {
     RInterlocked.Increment(ref _numReaders);
 }
Beispiel #12
0
            public void Depart()
            {
                int index = GetIndex();

                RInterlocked.Decrement(ref _occupancyCounts[index]);
            }
Beispiel #13
0
            public void Arrive()
            {
                int index = GetIndex();

                RInterlocked.Increment(ref _occupancyCounts[index]);
            }