public void PushLeft_IsAtomic() { //Arrange long pushCount = 0; long sum = 0; bool cancelled = false; var deque = new ConcurrentDeque <int>(); //keep adding items to the deque Action pushLeft = () => { Random rnd = new Random(); while (!cancelled) { int val = rnd.Next(1, 11); deque.PushLeft(val); Interlocked.Increment(ref pushCount); Interlocked.Add(ref sum, val); } }; //Act pushLeft.RunInParallel(() => cancelled = true, ThreadCount, RunningTime); //Assert VerifyState(deque, pushCount, sum); }
public void EnumeratorDoesNotIncludeConcurrentModifications() { //Arrange var arr = new[] { 1, 2, 3 }; var deque = new ConcurrentDeque <Int32>(arr); Int32 item; //Act var iterator = deque.GetEnumerator(); iterator.MoveNext(); deque.TryPopLeft(out item); deque.TryPopLeft(out item); deque.PushLeft(6); deque.TryPopRight(out item); deque.PushRight(6); //Assert Assert.AreEqual(1, iterator.Current); Assert.True(iterator.MoveNext()); Assert.AreEqual(2, iterator.Current); Assert.True(iterator.MoveNext()); Assert.AreEqual(3, iterator.Current); Assert.False(iterator.MoveNext()); }
private static void ExecuteOp(ConcurrentDeque <int> deque, int op) { int item; switch (op) { case PopLeft: deque.TryPopLeft(out item); break; case PopRight: deque.TryPopRight(out item); break; case PushLeft: deque.PushLeft(10); break; case PushRight: deque.PushRight(10); break; default: throw new InvalidOperationException(); } }
public void TryPopLeft_IsAtomic() { //Arrange const int initialCount = 5000000; const double stopAt = initialCount * 0.9; int popCount = 0; var deque = new ConcurrentDeque <int>(); for (int i = 0; i < initialCount; i++) { deque.PushLeft(i); } Action popLeft = () => { while (popCount <= stopAt) { int i; Assert.True(deque.TryPopLeft(out i)); Interlocked.Increment(ref popCount); } }; //Act popLeft.RunInParallel(ThreadCount); //Assert var expectedCount = initialCount - popCount; long expectedSum = Enumerable.Range(0, expectedCount).LongSum(); VerifyState(deque, expectedCount, expectedSum); }
public void PushLeft_AppendsNode_ToEmptyDeque() { var deque = new ConcurrentDeque <int>(); deque.PushLeft(1); Assert.Equal(new[] { 1 }, deque); }
public void PushLeft_AppendsNode_ToNonEmptyList() { var deque = new ConcurrentDeque <int>(new[] { 1, 2, 3 }); deque.PushLeft(0); Assert.Equal(new[] { 0, 1, 2, 3 }, deque); }
public void PushLeftAppendsNodeToNonEmptyList() { var deque = new ConcurrentDeque <Int32>(new[] { 1, 2, 3 }); deque.PushLeft(0); Assert.AreEqual(new[] { 0, 1, 2, 3 }, deque); }
public void PushLeftAppendsNodeToEmptyDeque() { var deque = new ConcurrentDeque <Int32>(); deque.PushLeft(1); Assert.AreEqual(new[] { 1 }, deque); }
public void PushLeftKeepsReferenceToPreviousLeftNode() { //Arrange const Int32 prevValue = 1; const Int32 value = 5; var deque = new ConcurrentDeque <Int32>(); deque.PushLeft(prevValue); //Act deque.PushLeft(value); //Assert var anchor = deque._anchor; var newNode = anchor._left; Assert.AreEqual(prevValue, newNode._right._value); }
public void PushLeftStabilizesDeque() { //Arrange const Int32 prevValue = 1; const Int32 value = 5; var deque = new ConcurrentDeque <Int32>(); deque.PushLeft(prevValue); //Act deque.PushLeft(value); //Assert var anchor = deque._anchor; var newNode = anchor._left; Assert.AreSame(newNode, newNode._right._left); Assert.AreEqual(ConcurrentDeque <Int32> .DequeStatus.Stable, anchor._status); }
public void PushLeftAppendsNodeToEmptyList() { //Arrange const Int32 value = 5; var deque = new ConcurrentDeque <Int32>(); //Act deque.PushLeft(value); //Assert var anchor = deque._anchor; Assert.NotNull(anchor._right); Assert.NotNull(anchor._left); Assert.AreSame(anchor._left, anchor._right); Assert.AreEqual(value, anchor._left._value); }
public void PushLeftAppendsNodeToNonEmptyList() { //Arrange const Int32 value = 5; var deque = new ConcurrentDeque <Int32>(); deque.PushRight(1); //Act deque.PushLeft(value); //Assert var anchor = deque._anchor; var leftmostNode = anchor._left; Assert.NotNull(leftmostNode); Assert.AreEqual(value, leftmostNode._value); }
public void InterleavedPushPopLeftOps() { //Arrange var deque = new ConcurrentDeque <int>(); long sum = 0; long nodeCount = 0; bool cancelled = false; Action action = () => { Random rnd = new Random(); while (!cancelled) { //slightly biased towards "push" if (rnd.NextDouble() >= 0.45) { //push var val = rnd.Next(1, 51); deque.PushLeft(val); Interlocked.Increment(ref nodeCount); Interlocked.Add(ref sum, val); } else { //pop int val; if (deque.TryPopLeft(out val)) { Interlocked.Decrement(ref nodeCount); Interlocked.Add(ref sum, -val); } } } }; //Act action.RunInParallel(() => cancelled = true, ThreadCount, RunningTime); //Assert VerifyState(deque, nodeCount, sum); }
public void InterleavedOps() { //Arrange var deque = new ConcurrentDeque <int>(); long sum = 0; long nodeCount = 0; bool cancelled = false; bool shouldPush = true; Action action = () => { Random rnd = new Random(); while (!cancelled) { if (shouldPush) { //push to either end var val = rnd.Next(1, 51); if (rnd.NextDouble() > 0.50) { deque.PushLeft(val); } else { deque.PushRight(val); } Interlocked.Increment(ref nodeCount); Interlocked.Add(ref sum, val); //start popping if (nodeCount >= 10000) { shouldPush = false; } } else { //pop from either end int val; if (rnd.NextDouble() > 0.50) { if (deque.TryPopLeft(out val)) { Interlocked.Decrement(ref nodeCount); Interlocked.Add(ref sum, -val); } } else { if (deque.TryPopRight(out val)) { Interlocked.Decrement(ref nodeCount); Interlocked.Add(ref sum, -val); } } //start pushing if (nodeCount == 0) { shouldPush = true; } } } }; //Act action.RunInParallel(() => cancelled = true, ThreadCount, RunningTime); //Assert VerifyState(deque, nodeCount, sum); }
public static void Main(string[] args) { var options = new Options(); var deque = new ConcurrentDeque <int>(Enumerable.Repeat(1, 100000)); bool cancelled = false; //parse arguments if (!CommandLine.Parser.Default.ParseArgumentsStrict(args, options)) { return; } Setup(options); using (var countersContainer = CreateContainer(options)) { //action to be executed by each thread - concurrently mutate the deque Action action = () => { int i = 0; int poppedValue; while (!cancelled) { //pop from/push onto the deque i++; if (i % 4 == 0) { deque.PushLeft(1); } else if (i % 3 == 0) { deque.PushRight(1); } else if (i % 2 == 0) { deque.TryPopLeft(out poppedValue); } else { deque.TryPopRight(out poppedValue); } //increment counters countersContainer.Increment(); } countersContainer.Complete(); }; Action cancel = () => { cancelled = true; }; //launch a set of threads to mutate the deque concurrently action.RunInParallel(cancel, _threadCount, _runningTime); countersContainer.PrintCounters(); } }