// adds to the current position public bool TryAddReadingGate(uint length, out ReadingGate gate) { _gateSemaphoreSlim.Wait(); lock (_gateLocker) { gate = null; if (Volatile.Read(ref _gateState) == -1L) { return(false); } gate = new ReadingGate { inEffect = true, gpos = _state._readPosition, length = length }; AtomicSecureIndexPosAndStore(gate); _abaPrevention++; // Console.WriteLine("gate added for " + gate.gpos + " len " + gate.length + " at index " + gate.index); } return(true); }
// adds to the current position internal ReadingGate AddReadingGate(uint length) { if (_gateState == -1) throw new Exception("Max gates reached"); var gate = new ReadingGate() { gpos = _readP._readPosition, length = length }; AtomicSecureIndexPosAndStore(gate); return gate; }
internal void RemoveReadingGate(ReadingGate gate) { if (gate.inEffect == false) { return; } gate.inEffect = false; AtomicRemoveAtIndex(gate.index); // if waiting for write coz of gate, given them another chance _waitingStrategy.SignalReadDone(); }
private volatile int _gateState = 0; // 11111111 11111111 11111111 11111111 // adds to the current position internal ReadingGate AddReadingGate(uint length) { if (_gateState == -1) { throw new Exception("Max gates reached"); } var gate = new ReadingGate() { gpos = _readP._readPosition, length = length }; AtomicSecureIndexPosAndStore(gate); return(gate); }
// private void AtomicSecureIndexPosAndStore(ReadingGate gate) { while (true) { long curState = Volatile.Read(ref _gateState); var emptyIndex = -1; // find empty spot for (int i = 0; i < MaxGates; i++) { long mask = 1L << i; if ((curState & mask) == 0) { emptyIndex = i; break; } } if (emptyIndex == -1) { continue; // try again from the beginning } long newState = curState | (1L << emptyIndex); gate.index = emptyIndex; #pragma warning disable 420 if (Interlocked.CompareExchange(ref _gateState, newState, curState) != curState) #pragma warning restore 420 { // state was changed. try again continue; } _gates[emptyIndex] = gate; // race between changing the state and saving to array. break; } }
// public void RemoveReadingGate(ReadingGate gate) { lock (_gateLocker) { lock (gate) { if (gate.inEffect == false) { return; } gate.inEffect = false; AtomicRemoveAtIndex(gate.index); } _abaPrevention++; } _gateSemaphoreSlim.Release(); // Console.WriteLine("RemoveReadingGate for " + gate.gpos + " len " + gate.length + " at " + gate.index); // if waiting for write coz of gate, given them another chance _readLock.Set(); }
public int Read(byte[] buffer, int offset, int count, bool fillBuffer = false, ReadingGate fromGate = null) { #if DEBUG if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "must be greater or equal to 0"); } if (count <= 0) { throw new ArgumentOutOfRangeException("count", "must be greater than 0"); } #endif int totalRead = 0; while (totalRead < count) { // AvailableAndPos availPos = this.InternalGetReadyToReadEntries(count - totalRead, fromGate); int available; int readPos = this.InternalGetReadyToReadEntries(count - totalRead, out available, fromGate); // var available = (int) availPos.available; if (available == 0) { if (fillBuffer) { _waitingStrategy.WaitForWrite(); continue; } break; } // int readPos = (int) availPos.position; int dstOffset = offset + totalRead; Buffer.BlockCopy(_buffer, readPos, buffer, dstOffset, available); totalRead += available; if (fromGate != null) { fromGate.gpos += (uint)available; fromGate.length -= (uint)available; } else { // if (!fillBuffer) break; _readP._readPosition += (uint)available; // volative write } _waitingStrategy.SignalReadDone(); // signal - if someone is waiting } return(totalRead); }
public int Read(byte[] buffer, int offset, int count, bool fillBuffer = false, ReadingGate fromGate = null) { #if DEBUG if (offset < 0) throw new ArgumentOutOfRangeException("offset", "must be greater or equal to 0"); if (count <= 0) throw new ArgumentOutOfRangeException("count", "must be greater than 0"); #endif int totalRead = 0; while (totalRead < count) { // AvailableAndPos availPos = this.InternalGetReadyToReadEntries(count - totalRead, fromGate); int available; int readPos = this.InternalGetReadyToReadEntries(count - totalRead, out available, fromGate); // var available = (int) availPos.available; if (available == 0) { if (fillBuffer) { _waitingStrategy.WaitForWrite(); continue; } break; } // int readPos = (int) availPos.position; int dstOffset = offset + totalRead; Buffer.BlockCopy(_buffer, readPos, buffer, dstOffset, available); totalRead += available; if (fromGate != null) { fromGate.gpos += (uint) available; fromGate.length -= (uint)available; } else { // if (!fillBuffer) break; _readP._readPosition += (uint)available; // volative write } _waitingStrategy.SignalReadDone(); // signal - if someone is waiting } return totalRead; }
// [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif internal int InternalGetReadyToReadEntries(int desiredCount, out int available, ReadingGate fromGate = null) { uint bufferSize = _state._bufferSize; uint readCursor = _state._readPositionCopy; // uint writeCursor = _state._writePosition; // volative read uint writeCursor = _state._writePositionCopy; if (readCursor == writeCursor || writeCursor - readCursor >= bufferSize) { writeCursor = _state._writePosition; } uint writePos = writeCursor & (bufferSize - 1); // (writeCursor % _bufferSize); uint readPos = readCursor & (bufferSize - 1); // (readCursor % _bufferSize); uint entriesFree; if (fromGate != null) { // Console.WriteLine("Reading from gate " + fromGate.index + ". Real readCursor g: " + readCursor + " l: readPos " + readPos + // " replaced by g: " + fromGate.gpos + " l: " + (fromGate.gpos & (bufferSize - 1)) + // " diff is " + (writeCursor - fromGate.gpos)); readPos = fromGate.gpos & (bufferSize - 1); // entriesFree = fromGate.length; desiredCount = Math.Min(desiredCount, (int)fromGate.length); } // else { var writeHasWrapped = writePos < readPos; if (writeHasWrapped) // so everything ahead of readpos is available { entriesFree = bufferSize - readPos; } else { entriesFree = writePos - readPos; } } #if DEBUG if (entriesFree > bufferSize) { var msg = "Assert failed read: " + entriesFree + " must be less or equal to " + (BufferSize); System.Diagnostics.Debug.WriteLine(msg); throw new Exception(msg); } #endif if (fromGate != null) { available = InternalMin(entriesFree, desiredCount); } else { available = InternalMin(entriesFree, desiredCount); } return((int)readPos); }
public int Read(byte[] buffer, int offset, int count, bool fillBuffer = false, ReadingGate fromGate = null) { #if DEBUG if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "must be greater or equal to 0"); } if (count <= 0) { throw new ArgumentOutOfRangeException("count", "must be greater than 0"); } #endif int totalRead = 0; while (totalRead < count) { int available; int readPos = this.InternalGetReadyToReadEntries(count - totalRead, out available, fromGate); if (_state._resetApplied) { break; } if (available == 0) { if (fillBuffer) { _writeLock.Wait(); continue; } break; } int dstOffset = offset + totalRead; Buffer.BlockCopy(_buffer, readPos + _bufferPadding, buffer, dstOffset, available); totalRead += available; if (fromGate != null) { lock (fromGate) { fromGate.gpos += (uint)available; fromGate.length -= (uint)available; } } else { // if (!fillBuffer) break; var newReadPos = _state._readPosition + (uint)available; _state._readPosition = newReadPos; // volative write _state._readPositionCopy = newReadPos; } _readLock.Set(); // signal - if someone is waiting } return(totalRead); }
internal int InternalGetReadyToReadEntries(int desiredCount, out int available, ReadingGate fromGate = null) { uint bufferSize = _bufferSize; uint writeCursor = _writeP._writePosition; // volative read uint readCursor = _readP._readPosition; // volative read uint writePos = writeCursor & (bufferSize - 1); // (writeCursor % _bufferSize); uint readPos = readCursor & (bufferSize - 1); // (readCursor % _bufferSize); uint entriesFree; if (fromGate != null) { // Console.WriteLine("Reading from gate. Real readpos " + readPos + " replaced by " + fromGate.pos); readPos = fromGate.gpos & (bufferSize - 1); // entriesFree = fromGate.length; desiredCount = Math.Min(desiredCount, (int)fromGate.length); } // else { var writeHasWrapped = writePos < readPos; if (writeHasWrapped) // so everything ahead of readpos is available { entriesFree = bufferSize - readPos; } else { entriesFree = writePos - readPos; } } #if DEBUG if (entriesFree > _bufferSize) { var msg = "Assert failed read: " + entriesFree + " must be less or equal to " + (BufferSize); System.Diagnostics.Debug.WriteLine(msg); throw new Exception(msg); } #endif // uint available; // if (fromGate != null) // { // available = Math.Min(entriesFree, (uint) desiredCount); // } // else { available = (int)Math.Min(entriesFree, (uint)desiredCount); } // return available; // return new AvailableAndPos() { available = (int)available, position = (int)readPos }; return((int)readPos); }
// internal struct AvailableAndPos // { // public int available, position; // } private void AtomicSecureIndexPosAndStore(ReadingGate gate) { while (true) { var curState = _gateState; // vol read var emptyIndex = -1; // find empty spot for (var i = 0; i < MaxGates; i++) { int mask = 1 << i; if ((curState & mask) == 0) { emptyIndex = i; break; } } if (emptyIndex == -1) continue; // try again from the beginning int newState = curState | (1 << emptyIndex); gate.index = emptyIndex; #pragma warning disable 420 if (Interlocked.CompareExchange(ref _gateState, newState, curState) != curState) #pragma warning restore 420 { // state was changed. try again continue; } _gates[emptyIndex] = gate; // race between changing the state and saving to array. break; } }
internal void RemoveReadingGate(ReadingGate gate) { if (gate.inEffect == false) return; gate.inEffect = false; AtomicRemoveAtIndex(gate.index); // if waiting for write coz of gate, given them another chance _waitingStrategy.SignalReadDone(); }
internal int InternalGetReadyToReadEntries(int desiredCount, out int available, ReadingGate fromGate = null) { uint bufferSize = _bufferSize; uint writeCursor = _writeP._writePosition; // volative read uint readCursor = _readP._readPosition; // volative read uint writePos = writeCursor & (bufferSize - 1); // (writeCursor % _bufferSize); uint readPos = readCursor & (bufferSize - 1); // (readCursor % _bufferSize); uint entriesFree; if (fromGate != null) { // Console.WriteLine("Reading from gate. Real readpos " + readPos + " replaced by " + fromGate.pos); readPos = fromGate.gpos & (bufferSize - 1); // entriesFree = fromGate.length; desiredCount = Math.Min(desiredCount, (int) fromGate.length); } // else { var writeHasWrapped = writePos < readPos; if (writeHasWrapped) // so everything ahead of readpos is available { entriesFree = bufferSize - readPos; } else { entriesFree = writePos - readPos; } } #if DEBUG if (entriesFree > _bufferSize) { var msg = "Assert failed read: " + entriesFree + " must be less or equal to " + (BufferSize); System.Diagnostics.Debug.WriteLine(msg); throw new Exception(msg); } #endif // uint available; // if (fromGate != null) // { // available = Math.Min(entriesFree, (uint) desiredCount); // } // else { available = (int) Math.Min(entriesFree, (uint)desiredCount); } // return available; // return new AvailableAndPos() { available = (int)available, position = (int)readPos }; return (int) readPos; }
public RingBufferStreamReadBarrier(RingBufferStreamAdapter innerStream, int length) { _ringBuffer = innerStream._ringBuffer; // _length = length; _gate = _ringBuffer.AddReadingGate((uint)length); }
public RingBufferStreamReadBarrier(RingBufferStreamAdapter innerStream, int length) { _ringBuffer = innerStream._ringBuffer; // _length = length; _gate = _ringBuffer.AddReadingGate((uint)length); }