public CompareAndSet ( long expectedSequence, long nextSequence ) : bool | ||
expectedSequence | long | the expected value for the sequence |
nextSequence | long | the new value for the sequence |
return | bool |
internal long NextInternal(int n) { long current; long next; var spinWait = default(AggressiveSpinWait); do { current = _cursor.Value; next = current + n; long wrapPoint = next - _bufferSize; long cachedGatingSequence = _gatingSequenceCache.Value; if (wrapPoint > cachedGatingSequence || cachedGatingSequence > current) { long gatingSequence = Util.GetMinimumSequence(Volatile.Read(ref _gatingSequences), current); if (wrapPoint > gatingSequence) { spinWait.SpinOnce(); continue; } _gatingSequenceCache.SetValue(gatingSequence); } else if (_cursor.CompareAndSet(current, next)) { break; } } while (true); return(next); }
///<summary> /// Serialise publishers in sequence and set cursor to latest available sequence. ///</summary> ///<param name="sequence">sequence to be applied</param> ///<param name="cursor">cursor to serialise against.</param> ///<param name="batchSize">batchSize of the sequence.</param> public override void SerialisePublishing(long sequence, Sequence cursor, long batchSize) { var spinWait = default(SpinWait); while (sequence - cursor.Value > _pendingPublication.Length) { spinWait.SpinOnce(); } long expectedSequence = sequence - batchSize; for (long pendingSequence = expectedSequence + 1; pendingSequence <= sequence; pendingSequence++) { _pendingPublication.WriteCompilerOnlyFence((int)pendingSequence & _pendingMask, pendingSequence); } _pendingPublication.WriteFullFence((int)sequence & _pendingMask, sequence); long cursorSequence = cursor.Value; if (cursorSequence >= sequence) { return; } expectedSequence = Math.Max(expectedSequence, cursorSequence); long nextSequence = expectedSequence + 1; while (cursor.CompareAndSet(expectedSequence, nextSequence)) { expectedSequence = nextSequence; nextSequence++; if (_pendingPublication.ReadFullFence((int)nextSequence & _pendingMask) != nextSequence) { break; } } }
///<summary> /// Serialise publishers in sequence and set cursor to latest available sequence. ///</summary> ///<param name="sequence">sequence to be applied</param> ///<param name="cursor">cursor to serialise against.</param> ///<param name="batchSize">batchSize of the sequence.</param> public void SerialisePublishing(long sequence, Sequence cursor, long batchSize) { var spinWait = default(SpinWait); while (sequence - cursor.Value > _pendingPublication.Length) { spinWait.SpinOnce(); } long expectedSequence = sequence - batchSize; for (long pendingSequence = expectedSequence + 1; pendingSequence <= sequence; pendingSequence++) { _pendingPublication.WriteFullFence((int)pendingSequence & _pendingMask, pendingSequence); } if (cursor.Value != expectedSequence) { return; } long nextSequence = expectedSequence + 1; while (cursor.CompareAndSet(expectedSequence, nextSequence)) { expectedSequence = nextSequence; nextSequence++; if (_pendingPublication.ReadFullFence((int)nextSequence & _pendingMask) != nextSequence) { break; } } }
/// <summary> /// Atomically checks the available capacity of the ring buffer and claims the next sequence. Will /// throw InsufficientCapacityException if the capacity not available. /// </summary> /// <param name="availableCapacity">the capacity that should be available before claiming the next slot</param> /// <param name="delta">the number of slots to claim</param> /// <param name="dependentSequences">the set of sequences to check to ensure capacity is available</param> /// <returns>the slot after incrementing</returns> public long CheckAndIncrement(int availableCapacity, int delta, Sequence[] dependentSequences) { for (;;) { long sequence = _claimSequence.Value; if (HasAvailableCapacity(sequence, availableCapacity, dependentSequences)) { long nextSequence = sequence + delta; if (_claimSequence.CompareAndSet(sequence, nextSequence)) { return(nextSequence); } } else { throw InsufficientCapacityException.Instance; } } }
internal bool TryNextInternal(int n, out long sequence) { long current; long next; do { current = _cursor.Value; next = current + n; if (!HasAvailableCapacity(n, current)) { sequence = default; return(false); } }while (!_cursor.CompareAndSet(current, next)); sequence = next; return(true); }