public void ShouldOnlyClaimWhatsAvailable() { Sequence dependentSequence = new Sequence(); Sequence[] dependentSequences = { dependentSequence }; for (int j = 0; j < 1000; j++) { int numThreads = BufferSize * 2; IClaimStrategy claimStrategy = new MultiThreadedClaimStrategy(BufferSize); Volatile4.LongArray claimed = new Volatile4.LongArray(numThreads); Barrier barrier = new Barrier(numThreads); Thread[] ts = new Thread[numThreads]; for (int i = 0; i < numThreads; i++) { ts[i] = new Thread(() => { try { barrier.SignalAndWait(); long next = claimStrategy.CheckAndIncrement(1, 1, dependentSequences); claimed.AtomicIncrementAndGet((int)next); } catch (Exception e) { } }); } foreach (Thread t in ts) { t.Start(); } foreach (Thread t in ts) { t.Join(); } for (int i = 0; i < BufferSize; i++) { Assert.AreEqual(1L, claimed.ReadFullFence(i), "j = " + j + ", i = " + i); } for (int i = BufferSize; i < numThreads; i++) { Assert.AreEqual(0L, claimed.ReadFullFence(i), "j = " + j + ", i = " + i); } } }
///<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; } } }
public void ReadFullFenceReturnsInitialValue() { Assert.AreEqual(InitialValue, _volatile.ReadFullFence(0)); }
public void ShouldOnlyClaimWhatsAvailable() { Sequence dependentSequence = new Sequence(); Sequence[] dependentSequences = { dependentSequence }; for (int j = 0; j < 1000; j++) { int numThreads = BufferSize * 2; IClaimStrategy claimStrategy = new MultiThreadedClaimStrategy(BufferSize); Volatile4.LongArray claimed = new Volatile4.LongArray(numThreads); Barrier barrier = new Barrier(numThreads); Thread[] ts = new Thread[numThreads]; for (int i = 0; i < numThreads; i++) { ts[i] = new Thread(() => { try { barrier.SignalAndWait(); long next = claimStrategy.CheckAndIncrement(1, 1, dependentSequences); claimed.AtomicIncrementAndGet((int) next); } catch (Exception e) { } }); } foreach (Thread t in ts) { t.Start(); } foreach (Thread t in ts) { t.Join(); } for (int i = 0; i < BufferSize; i++) { Assert.AreEqual(1L, claimed.ReadFullFence(i), "j = " + j + ", i = " + i); } for (int i = BufferSize; i < numThreads; i++) { Assert.AreEqual(0L, claimed.ReadFullFence(i), "j = " + j + ", i = " + i); } } }