예제 #1
0
        // 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);
        }
예제 #2
0
        // 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;
        }
예제 #3
0
 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();
 }
예제 #4
0
        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);
        }
예제 #5
0
        //
        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;
            }
        }
예제 #6
0
        //
        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();
        }
예제 #7
0
        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);
        }
예제 #8
0
        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;
        }
예제 #9
0
        // [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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        //        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;
            }
        }
예제 #13
0
 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();
 }
예제 #14
0
        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);
 }