public void TestTwoTasksRequestingResourcesBothShouldSucceed() { int numOfThreads = 2; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreatePreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); Object resource1 = new object(); Object resource2 = new object(); List <int> list1 = new List <int>(); List <int> list2 = new List <int>(); Task t1 = CreateTaskWithResourceLock(id: 1, token: token1, resource1: resource1, resource2: resource2, list1); Task t2 = CreateTaskWithResourceLock(id: 2, token: token2, resource1: resource2, resource2: resource1, list2); taskScheduler.Register(t1, 5, 5000, token1); taskScheduler.Register(t2, 4, 5000, token2); t1.Start(taskScheduler); Task.Delay(500).Wait(); t2.Start(taskScheduler); Task.Delay(5000).Wait(); Assert.AreEqual(list1.Count, 2); Assert.AreEqual(list2.Count, 2); }
private static void PreemptingExampleNonPreemptingSchedulerMultipleTasks() { int numOfThreads = 2; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreateNonPreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token3 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token4 = taskScheduler.GetExecutionToken(); Task t1 = CreateTask(id: 1, token: token1); Task t2 = CreateTask(id: 2, token: token2); Task t3 = CreateTask(id: 3, token: token3); Task t4 = CreateTask(id: 4, token: token4); taskScheduler.Register(t1, 5, 2500, token1); taskScheduler.Register(t2, 4, 2500, token2); taskScheduler.Register(t3, 3, 2500, token3); taskScheduler.Register(t4, 2, 2500, token4); t1.Start(taskScheduler); t2.Start(taskScheduler); Task.Delay(1000).Wait(); t3.Start(taskScheduler); t4.Start(taskScheduler); taskScheduler.FinishScheduling(); }
public void Test10TasksOn5ThreadsPreemptingEachOther() { int numOfThreads = 5; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreatePreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token3 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token4 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token5 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token6 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token7 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token8 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token9 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token10 = taskScheduler.GetExecutionToken(); Object resource = new object(); Task t1 = CreateTaskWithResourceLock(id: 1, token: token1, resource: resource); Task t2 = CreateTaskWithResourceLock(id: 2, token: token2, resource: resource); Task t3 = CreateTaskWithResourceLock(id: 3, token: token3, resource: resource); Task t4 = CreateTaskWithResourceLock(id: 4, token: token4, resource: resource); Task t5 = CreateTaskWithResourceLock(id: 5, token: token5, resource: resource); Task t6 = CreateTaskWithResourceLock(id: 6, token: token6, resource: resource); Task t7 = CreateTaskWithResourceLock(id: 7, token: token7, resource: resource); Task t8 = CreateTaskWithResourceLock(id: 8, token: token8, resource: resource); Task t9 = CreateTaskWithResourceLock(id: 9, token: token9, resource: resource); Task t10 = CreateTaskWithResourceLock(id: 10, token: token10, resource: resource); taskScheduler.Register(t1, 1, 2500, token1); taskScheduler.Register(t2, 2, 2500, token2); taskScheduler.Register(t3, 3, 2500, token3); taskScheduler.Register(t4, 4, 2500, token4); taskScheduler.Register(t5, 5, 2500, token5); taskScheduler.Register(t6, 6, 2500, token6); taskScheduler.Register(t7, 7, 2500, token7); taskScheduler.Register(t8, 8, 2500, token8); taskScheduler.Register(t9, 9, 2500, token9); taskScheduler.Register(t10, 10, 2500, token10); t1.Start(taskScheduler); t2.Start(taskScheduler); t3.Start(taskScheduler); t4.Start(taskScheduler); t5.Start(taskScheduler); t6.Start(taskScheduler); t7.Start(taskScheduler); t8.Start(taskScheduler); t9.Start(taskScheduler); t10.Start(taskScheduler); Task.Delay(15000).Wait(); Assert.IsTrue(t1.IsCompleted); Assert.IsTrue(t2.IsCompleted); Assert.IsTrue(t3.IsCompleted); Assert.IsTrue(t4.IsCompleted); Assert.IsTrue(t5.IsCompleted); Assert.IsTrue(t6.IsCompleted); Assert.IsTrue(t7.IsCompleted); Assert.IsTrue(t8.IsCompleted); Assert.IsTrue(t9.IsCompleted); Assert.IsTrue(t10.IsCompleted); }
public void TestThreeTasksOnTwoThreadsPreemptingEachOther() { int numOfThreads = 2; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreatePreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token3 = taskScheduler.GetExecutionToken(); Object resource = new object(); Task t1 = CreateTaskWithResourceLock(id: 1, token: token1, resource: resource); Task t2 = CreateTaskWithResourceLock(id: 2, token: token2, resource: resource); Task t3 = CreateTask(id: 3, token: token3); taskScheduler.Register(t1, 5, 2500, token1); taskScheduler.Register(t2, 4, 2500, token2); taskScheduler.Register(t3, 3, 2500, token3); t1.Start(taskScheduler); Task.Delay(500).Wait(); t2.Start(taskScheduler); t3.Start(taskScheduler); Task.Delay(5000).Wait(); Assert.AreEqual(taskScheduler.CurrentlyExecutingTasksCount(), 0); }
private static void DeadlockDetectionExample() { int numOfThreads = 2; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreatePreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token3 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token4 = taskScheduler.GetExecutionToken(); Object resource1 = new object(); Object resource2 = new object(); Task t1 = CreateTaskWithResourceLock(id: 1, token: token1, resource1: resource1, resource2: resource2); Task t2 = CreateTaskWithResourceLock(id: 2, token: token2, resource1: resource2, resource2: resource1); Task t3 = CreateTaskWithResourceLock(id: 3, token: token3, resource1: resource1, resource2: resource2); Task t4 = CreateTaskWithResourceLock(id: 4, token: token4, resource1: resource2, resource2: resource1); taskScheduler.Register(t1, 5, 2500, token1); taskScheduler.Register(t2, 4, 2500, token2); taskScheduler.Register(t3, 3, 2500, token3); taskScheduler.Register(t4, 2, 2500, token4); t1.Start(taskScheduler); t2.Start(taskScheduler); t3.Start(taskScheduler); t4.Start(taskScheduler); }
internal TaskWantsToUnlockResourceEvent(SimpleTaskScheduler scheduler, ExecutionToken taskToken, EventWaitHandle taskNotifier, object resource) { this.scheduler = scheduler; this.taskToken = taskToken; this.taskNotifier = taskNotifier; this.resource = resource; }
public void TestCreationOfNonPreemptiveSimpleTaskSchedulerWithTwoThreads() { int numberOfThreads = 2; SimpleTaskScheduler st = SimpleTaskScheduler.CreateNonPreemptive(numberOfThreads); Assert.AreEqual(numberOfThreads, st.GetMaxParallelTasks()); Assert.AreEqual(false, st.IsSchedulerPreemptive()); }
private static void BaseClassExample() { int numOfThreads = 1; TaskScheduler taskScheduler = SimpleTaskScheduler.CreateNonPreemptive(numOfThreads); Task t = CreateTask(id: 1); t.Start(taskScheduler); ((SimpleTaskScheduler)taskScheduler).FinishScheduling(); }
public void TestCreationOfPreemptiveSimpleTaskSchedulerWithMinusThreeThreads() { int numberOfThreads = -3; try { SimpleTaskScheduler st = SimpleTaskScheduler.CreatePreemptive(numberOfThreads); Assert.Fail(); } catch (ArgumentOutOfRangeException ex) { } }
public void TestSchedulingOfPreemptiveUsingBaseClassShouldFailQueueing() { int numOfThreads = 2; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreatePreemptive(numOfThreads); TaskScheduler baseTaskScheduler = taskScheduler; Task t = CreateTask(id: 1, token: taskScheduler.GetExecutionToken()); t.Start(baseTaskScheduler); Assert.IsFalse(taskScheduler.IsTaskCurrentlyExecuting(t)); }
public void TestSchedulingOfNonPreemptiveUsingBaseClassShouldSucceedQueueing() { int numOfThreads = 2; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreateNonPreemptive(numOfThreads); TaskScheduler baseTaskScheduler = taskScheduler; Task t = CreateTask(id: 1, token: taskScheduler.GetExecutionToken()); t.Start(baseTaskScheduler); Task.Delay(500).Wait(); Assert.IsTrue(taskScheduler.IsTaskCurrentlyExecuting(t)); }
public void TestTwoTasksWithNoResourceLocking() { int numOfThreads = 1; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreatePreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); Task t1 = CreateTask(id: 1, token: token1); Task t2 = CreateTask(id: 2, token: token2); taskScheduler.Register(t1, 5, 2500, token1); taskScheduler.Register(t2, 4, 2500, token2); t1.Start(taskScheduler); Task.Delay(500).Wait(); t2.Start(taskScheduler); Assert.AreEqual(taskScheduler.CurrentlyExecutingTasksCount(), 1); }
private static void SingleThreadPreemptingExampleNonPreemptingScheduler() { int numOfThreads = 1; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreateNonPreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); Task t1 = CreateTask(id: 1, token: token1); Task t2 = CreateTask(id: 2, token: token2); taskScheduler.Register(t1, 5, 2500, token1); taskScheduler.Register(t2, 4, 2500, token2); t1.Start(taskScheduler); Task.Delay(1000).Wait(); t2.Start(taskScheduler); taskScheduler.FinishScheduling(); }
private static void PriorityInversionExample2() { int numOfThreads = 1; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreatePreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); Object resource = new Object(); Task t1 = CreateTaskWithResourceLockAndUnlockResource(id: 1, token: token1, resource); Task t2 = CreateTaskWithResourceLockAndUnlockResource(id: 2, token: token2, resource); taskScheduler.Register(t1, 5, 2500, token1); taskScheduler.Register(t2, 4, 2500, token2); t1.Start(taskScheduler); Task.Delay(1000).Wait(); t2.Start(taskScheduler); taskScheduler.FinishScheduling(); }
public void TestTwoTasksWithOneResourceLockingAndGettingMaxPriority() { int numOfThreads = 1; SimpleTaskScheduler taskScheduler = SimpleTaskScheduler.CreatePreemptive(numOfThreads); SimpleTaskScheduler.ExecutionToken token1 = taskScheduler.GetExecutionToken(); SimpleTaskScheduler.ExecutionToken token2 = taskScheduler.GetExecutionToken(); Task t1 = CreateTaskWithResourceLock(id: 1, token: token1, resource: new object());; Task t2 = CreateTask(id: 2, token: token2); taskScheduler.Register(t1, 5, 2500, token1); taskScheduler.Register(t2, 4, 2500, token2); t1.Start(taskScheduler); Task.Delay(500).Wait(); t2.Start(taskScheduler); Task.Delay(2000).Wait(); Assert.IsTrue(taskScheduler.IsTaskCurrentlyExecuting(t2)); }
internal TaskCompletedEvent(SimpleTaskScheduler scheduler, Task completedTask) { this.scheduler = scheduler; this.completedTask = completedTask; }
internal CancelTaskIfExistsEvent(SimpleTaskScheduler scheduler, Task taskToBeCancelled) { this.scheduler = scheduler; this.taskToBeCancelled = taskToBeCancelled; }
internal ScheduleTasksEvent(SimpleTaskScheduler scheduler) { this.scheduler = scheduler; }
//[Fact(Skip = "Outerloop")] public void RunActionBlockConformanceTests() { // SYNC // Do everything twice - once through OfferMessage and Once through Post for (FeedMethod feedMethod = FeedMethod._First; feedMethod < FeedMethod._Count; feedMethod++) { Func <DataflowBlockOptions, TargetProperties <int> > actionBlockFactory = options => { ITargetBlock <int> target = new ActionBlock <int>(i => TrackCaptures(i), (ExecutionDataflowBlockOptions)options); return(new TargetProperties <int> { Target = target, Capturer = target, ErrorVerifyable = true }); }; CancellationTokenSource cancellationSource = new CancellationTokenSource(); var defaultOptions = new ExecutionDataflowBlockOptions(); var dopOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; var mptOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, MaxMessagesPerTask = 1 }; var cancellationOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, MaxMessagesPerTask = 1, CancellationToken = cancellationSource.Token }; var spscOptions = new ExecutionDataflowBlockOptions { SingleProducerConstrained = true }; var spscMptOptions = new ExecutionDataflowBlockOptions { SingleProducerConstrained = true, MaxMessagesPerTask = 10 }; Assert.True(FeedTarget(actionBlockFactory, defaultOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, dopOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, mptOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, mptOptions, 1, Intervention.Complete, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, cancellationOptions, 1, Intervention.Cancel, cancellationSource, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, spscOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, spscOptions, 1, Intervention.Complete, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, spscMptOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, spscMptOptions, 1, Intervention.Complete, null, feedMethod, true)); } // Test scheduler usage { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { var sts = new SimpleTaskScheduler(); var options = new ExecutionDataflowBlockOptions { TaskScheduler = sts, MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, MaxMessagesPerTask = 1 }; if (trial == 0) { options.SingleProducerConstrained = true; } var ab = new ActionBlock <int>(i => localPassed &= TaskScheduler.Current.Id == sts.Id, options); for (int i = 0; i < 2; i++) { ab.Post(i); } ab.Complete(); ab.Completion.Wait(); } Assert.True(localPassed, string.Format("{0}: Correct scheduler usage", localPassed ? "Success" : "Failure")); } // Test count { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { var barrier1 = new Barrier(2); var barrier2 = new Barrier(2); var ab = new ActionBlock <int>(i => { barrier1.SignalAndWait(); barrier2.SignalAndWait(); }, new ExecutionDataflowBlockOptions { SingleProducerConstrained = (trial == 0) }); for (int iter = 0; iter < 2; iter++) { for (int i = 1; i <= 2; i++) { ab.Post(i); } for (int i = 1; i >= 0; i--) { barrier1.SignalAndWait(); localPassed &= i == ab.InputCount; barrier2.SignalAndWait(); } } } Assert.True(localPassed, string.Format("{0}: InputCount", localPassed ? "Success" : "Failure")); } // Test ordering { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { int prev = -1; var ab = new ActionBlock <int>(i => { if (prev + 1 != i) { localPassed &= false; } prev = i; }, new ExecutionDataflowBlockOptions { SingleProducerConstrained = (trial == 0) }); for (int i = 0; i < 2; i++) { ab.Post(i); } ab.Complete(); ab.Completion.Wait(); } Assert.True(localPassed, string.Format("{0}: Correct ordering", localPassed ? "Success" : "Failure")); } // Test non-greedy { bool localPassed = true; var barrier = new Barrier(2); var ab = new ActionBlock <int>(i => { barrier.SignalAndWait(); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 }); ab.SendAsync(1); Task.Delay(200).Wait(); var sa2 = ab.SendAsync(2); localPassed &= !sa2.IsCompleted; barrier.SignalAndWait(); // for SendAsync(1) barrier.SignalAndWait(); // for SendAsync(2) localPassed &= sa2.Wait(100); int total = 0; ab = new ActionBlock <int>(i => { Interlocked.Add(ref total, i); Task.Delay(1).Wait(); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 }); for (int i = 1; i <= 100; i++) { ab.SendAsync(i); } SpinWait.SpinUntil(() => total == ((100 * 101) / 2), 30000); localPassed &= total == ((100 * 101) / 2); Assert.True(localPassed, string.Format("total={0} (must be {1})", total, (100 * 101) / 2)); Assert.True(localPassed, string.Format("{0}: Non-greedy support", localPassed ? "Success" : "Failure")); } // Test that OperationCanceledExceptions are ignored { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { int sumOfOdds = 0; var ab = new ActionBlock <int>(i => { if ((i % 2) == 0) { throw new OperationCanceledException(); } sumOfOdds += i; }, new ExecutionDataflowBlockOptions { SingleProducerConstrained = (trial == 0) }); for (int i = 0; i < 4; i++) { ab.Post(i); } ab.Complete(); ab.Completion.Wait(); localPassed = sumOfOdds == (1 + 3); } Assert.True(localPassed, string.Format("{0}: OperationCanceledExceptions are ignored", localPassed ? "Success" : "Failure")); } // Test using a precanceled token { bool localPassed = true; try { var cts = new CancellationTokenSource(); cts.Cancel(); var dbo = new ExecutionDataflowBlockOptions { CancellationToken = cts.Token }; var ab = new ActionBlock <int>(i => { }, dbo); localPassed &= ab.Post(42) == false; localPassed &= ab.InputCount == 0; localPassed &= ab.Completion != null; ab.Complete(); } catch (Exception) { localPassed = false; } Assert.True(localPassed, string.Format("{0}: Precanceled tokens work correctly", localPassed ? "Success" : "Failure")); } // Test faulting { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { var ab = new ActionBlock <int>(i => { throw new InvalidOperationException(); }, new ExecutionDataflowBlockOptions { SingleProducerConstrained = (trial == 0) }); ab.Post(42); ab.Post(1); ab.Post(2); ab.Post(3); try { localPassed &= ab.Completion.Wait(5000); } catch { } localPassed &= ab.Completion.IsFaulted; localPassed &= SpinWait.SpinUntil(() => ab.InputCount == 0, 500); localPassed &= ab.Post(4) == false; } Assert.True(localPassed, string.Format("{0}: Faulted handled correctly", localPassed ? "Success" : "Failure")); } // ASYNC (a copy of the sync but with constructors returning Task instead of void // Do everything twice - once through OfferMessage and Once through Post for (FeedMethod feedMethod = FeedMethod._First; feedMethod < FeedMethod._Count; feedMethod++) { Func <DataflowBlockOptions, TargetProperties <int> > actionBlockFactory = options => { ITargetBlock <int> target = new ActionBlock <int>(i => TrackCapturesAsync(i), (ExecutionDataflowBlockOptions)options); return(new TargetProperties <int> { Target = target, Capturer = target, ErrorVerifyable = true }); }; CancellationTokenSource cancellationSource = new CancellationTokenSource(); var defaultOptions = new ExecutionDataflowBlockOptions(); var dopOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; var mptOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, MaxMessagesPerTask = 10 }; var cancellationOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, MaxMessagesPerTask = 100, CancellationToken = cancellationSource.Token }; Assert.True(FeedTarget(actionBlockFactory, defaultOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, defaultOptions, 10, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, dopOptions, 1000, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, mptOptions, 10000, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, mptOptions, 10000, Intervention.Complete, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, cancellationOptions, 10000, Intervention.Cancel, cancellationSource, feedMethod, true)); } // Test scheduler usage { bool localPassed = true; var sts = new SimpleTaskScheduler(); var ab = new ActionBlock <int>(i => { localPassed &= TaskScheduler.Current.Id == sts.Id; return(Task.Factory.StartNew(() => { })); }, new ExecutionDataflowBlockOptions { TaskScheduler = sts, MaxDegreeOfParallelism = -1, MaxMessagesPerTask = 10 }); for (int i = 0; i < 2; i++) { ab.Post(i); } ab.Complete(); ab.Completion.Wait(); Assert.True(localPassed, string.Format("{0}: Correct scheduler usage", localPassed ? "Success" : "Failure")); } // Test count { bool localPassed = true; var barrier1 = new Barrier(2); var barrier2 = new Barrier(2); var ab = new ActionBlock <int>(i => Task.Factory.StartNew(() => { barrier1.SignalAndWait(); barrier2.SignalAndWait(); })); for (int iter = 0; iter < 2; iter++) { for (int i = 1; i <= 2; i++) { ab.Post(i); } for (int i = 1; i >= 0; i--) { barrier1.SignalAndWait(); localPassed &= i == ab.InputCount; barrier2.SignalAndWait(); } } Assert.True(localPassed, string.Format("{0}: InputCount", localPassed ? "Success" : "Failure")); } // Test ordering { bool localPassed = true; int prev = -1; var ab = new ActionBlock <int>(i => { return(Task.Factory.StartNew(() => { if (prev + 1 != i) { localPassed &= false; } prev = i; })); }); for (int i = 0; i < 2; i++) { ab.Post(i); } ab.Complete(); ab.Completion.Wait(); Assert.True(localPassed, string.Format("{0}: Correct ordering", localPassed ? "Success" : "Failure")); } // Test non-greedy { bool localPassed = true; var barrier = new Barrier(2); var ab = new ActionBlock <int>(i => { return(Task.Factory.StartNew(() => { barrier.SignalAndWait(); })); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 }); ab.SendAsync(1); Task.Delay(200).Wait(); var sa2 = ab.SendAsync(2); localPassed &= !sa2.IsCompleted; barrier.SignalAndWait(); // for SendAsync(1) barrier.SignalAndWait(); // for SendAsync(2) localPassed &= sa2.Wait(100); int total = 0; ab = new ActionBlock <int>(i => { return(Task.Factory.StartNew(() => { Interlocked.Add(ref total, i); Task.Delay(1).Wait(); })); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 }); for (int i = 1; i <= 100; i++) { ab.SendAsync(i); } SpinWait.SpinUntil(() => total == ((100 * 101) / 2), 30000); localPassed &= total == ((100 * 101) / 2); Assert.True(localPassed, string.Format("total={0} (must be {1})", total, (100 * 101) / 2)); Assert.True(localPassed, string.Format("{0}: Non-greedy support", localPassed ? "Success" : "Failure")); } // Test that OperationCanceledExceptions are ignored { bool localPassed = true; int sumOfOdds = 0; var ab = new ActionBlock <int>(i => { if ((i % 2) == 0) { throw new OperationCanceledException(); } return(Task.Factory.StartNew(() => { sumOfOdds += i; })); }); for (int i = 0; i < 4; i++) { ab.Post(i); } ab.Complete(); ab.Completion.Wait(); localPassed = sumOfOdds == (1 + 3); Assert.True(localPassed, string.Format("{0}: OperationCanceledExceptions are ignored", localPassed ? "Success" : "Failure")); } // Test that null task is ignored { bool localPassed = true; int sumOfOdds = 0; var ab = new ActionBlock <int>(i => { if ((i % 2) == 0) { return(null); } return(Task.Factory.StartNew(() => { sumOfOdds += i; })); }); for (int i = 0; i < 4; i++) { ab.Post(i); } ab.Complete(); ab.Completion.Wait(); localPassed = sumOfOdds == (1 + 3); Assert.True(localPassed, string.Format("{0}: null tasks are ignored", localPassed ? "Success" : "Failure")); } // Test faulting from the delegate { bool localPassed = true; var ab = new ActionBlock <int>(new Func <int, Task>(i => { throw new InvalidOperationException(); })); ab.Post(42); ab.Post(1); ab.Post(2); ab.Post(3); try { localPassed &= ab.Completion.Wait(100); } catch { } localPassed &= ab.Completion.IsFaulted; localPassed &= SpinWait.SpinUntil(() => ab.InputCount == 0, 500); localPassed &= ab.Post(4) == false; Assert.True(localPassed, string.Format("{0}: Faulted from delegate handled correctly", localPassed ? "Success" : "Failure")); } // Test faulting from the task { bool localPassed = true; var ab = new ActionBlock <int>(i => Task.Factory.StartNew(() => { throw new InvalidOperationException(); })); ab.Post(42); ab.Post(1); ab.Post(2); ab.Post(3); try { localPassed &= ab.Completion.Wait(100); } catch { } localPassed &= ab.Completion.IsFaulted; localPassed &= SpinWait.SpinUntil(() => ab.InputCount == 0, 500); localPassed &= ab.Post(4) == false; Assert.True(localPassed, string.Format("{0}: Faulted from task handled correctly", localPassed ? "Success" : "Failure")); } }
//[Fact(Skip = "Outerloop")] public void RunActionBlockConformanceTests() { // SYNC // Do everything twice - once through OfferMessage and Once through Post for (FeedMethod feedMethod = FeedMethod._First; feedMethod < FeedMethod._Count; feedMethod++) { Func<DataflowBlockOptions, TargetProperties<int>> actionBlockFactory = options => { ITargetBlock<int> target = new ActionBlock<int>(i => TrackCaptures(i), (ExecutionDataflowBlockOptions)options); return new TargetProperties<int> { Target = target, Capturer = target, ErrorVerifyable = true }; }; CancellationTokenSource cancellationSource = new CancellationTokenSource(); var defaultOptions = new ExecutionDataflowBlockOptions(); var dopOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; var mptOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, MaxMessagesPerTask = 1 }; var cancellationOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, MaxMessagesPerTask = 1, CancellationToken = cancellationSource.Token }; var spscOptions = new ExecutionDataflowBlockOptions { SingleProducerConstrained = true }; var spscMptOptions = new ExecutionDataflowBlockOptions { SingleProducerConstrained = true, MaxMessagesPerTask = 10 }; Assert.True(FeedTarget(actionBlockFactory, defaultOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, dopOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, mptOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, mptOptions, 1, Intervention.Complete, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, cancellationOptions, 1, Intervention.Cancel, cancellationSource, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, spscOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, spscOptions, 1, Intervention.Complete, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, spscMptOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, spscMptOptions, 1, Intervention.Complete, null, feedMethod, true)); } // Test scheduler usage { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { var sts = new SimpleTaskScheduler(); var options = new ExecutionDataflowBlockOptions { TaskScheduler = sts, MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, MaxMessagesPerTask = 1 }; if (trial == 0) options.SingleProducerConstrained = true; var ab = new ActionBlock<int>(i => localPassed &= TaskScheduler.Current.Id == sts.Id, options); for (int i = 0; i < 2; i++) ab.Post(i); ab.Complete(); ab.Completion.Wait(); } Assert.True(localPassed, string.Format("{0}: Correct scheduler usage", localPassed ? "Success" : "Failure")); } // Test count { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { var barrier1 = new Barrier(2); var barrier2 = new Barrier(2); var ab = new ActionBlock<int>(i => { barrier1.SignalAndWait(); barrier2.SignalAndWait(); }, new ExecutionDataflowBlockOptions { SingleProducerConstrained = (trial == 0) }); for (int iter = 0; iter < 2; iter++) { for (int i = 1; i <= 2; i++) ab.Post(i); for (int i = 1; i >= 0; i--) { barrier1.SignalAndWait(); localPassed &= i == ab.InputCount; barrier2.SignalAndWait(); } } } Assert.True(localPassed, string.Format("{0}: InputCount", localPassed ? "Success" : "Failure")); } // Test ordering { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { int prev = -1; var ab = new ActionBlock<int>(i => { if (prev + 1 != i) localPassed &= false; prev = i; }, new ExecutionDataflowBlockOptions { SingleProducerConstrained = (trial == 0) }); for (int i = 0; i < 2; i++) ab.Post(i); ab.Complete(); ab.Completion.Wait(); } Assert.True(localPassed, string.Format("{0}: Correct ordering", localPassed ? "Success" : "Failure")); } // Test non-greedy { bool localPassed = true; var barrier = new Barrier(2); var ab = new ActionBlock<int>(i => { barrier.SignalAndWait(); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 }); ab.SendAsync(1); Task.Delay(200).Wait(); var sa2 = ab.SendAsync(2); localPassed &= !sa2.IsCompleted; barrier.SignalAndWait(); // for SendAsync(1) barrier.SignalAndWait(); // for SendAsync(2) localPassed &= sa2.Wait(100); int total = 0; ab = new ActionBlock<int>(i => { Interlocked.Add(ref total, i); Task.Delay(1).Wait(); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 }); for (int i = 1; i <= 100; i++) ab.SendAsync(i); SpinWait.SpinUntil(() => total == ((100 * 101) / 2), 30000); localPassed &= total == ((100 * 101) / 2); Assert.True(localPassed, string.Format("total={0} (must be {1})", total, (100 * 101) / 2)); Assert.True(localPassed, string.Format("{0}: Non-greedy support", localPassed ? "Success" : "Failure")); } // Test that OperationCanceledExceptions are ignored { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { int sumOfOdds = 0; var ab = new ActionBlock<int>(i => { if ((i % 2) == 0) throw new OperationCanceledException(); sumOfOdds += i; }, new ExecutionDataflowBlockOptions { SingleProducerConstrained = (trial == 0) }); for (int i = 0; i < 4; i++) ab.Post(i); ab.Complete(); ab.Completion.Wait(); localPassed = sumOfOdds == (1 + 3); } Assert.True(localPassed, string.Format("{0}: OperationCanceledExceptions are ignored", localPassed ? "Success" : "Failure")); } // Test using a precanceled token { bool localPassed = true; try { var cts = new CancellationTokenSource(); cts.Cancel(); var dbo = new ExecutionDataflowBlockOptions { CancellationToken = cts.Token }; var ab = new ActionBlock<int>(i => { }, dbo); localPassed &= ab.Post(42) == false; localPassed &= ab.InputCount == 0; localPassed &= ab.Completion != null; ab.Complete(); } catch (Exception) { localPassed = false; } Assert.True(localPassed, string.Format("{0}: Precanceled tokens work correctly", localPassed ? "Success" : "Failure")); } // Test faulting { bool localPassed = true; for (int trial = 0; trial < 2; trial++) { var ab = new ActionBlock<int>(i => { throw new InvalidOperationException(); }, new ExecutionDataflowBlockOptions { SingleProducerConstrained = (trial == 0) }); ab.Post(42); ab.Post(1); ab.Post(2); ab.Post(3); try { localPassed &= ab.Completion.Wait(5000); } catch { } localPassed &= ab.Completion.IsFaulted; localPassed &= SpinWait.SpinUntil(() => ab.InputCount == 0, 500); localPassed &= ab.Post(4) == false; } Assert.True(localPassed, string.Format("{0}: Faulted handled correctly", localPassed ? "Success" : "Failure")); } // ASYNC (a copy of the sync but with constructors returning Task instead of void // Do everything twice - once through OfferMessage and Once through Post for (FeedMethod feedMethod = FeedMethod._First; feedMethod < FeedMethod._Count; feedMethod++) { Func<DataflowBlockOptions, TargetProperties<int>> actionBlockFactory = options => { ITargetBlock<int> target = new ActionBlock<int>(i => TrackCapturesAsync(i), (ExecutionDataflowBlockOptions)options); return new TargetProperties<int> { Target = target, Capturer = target, ErrorVerifyable = true }; }; CancellationTokenSource cancellationSource = new CancellationTokenSource(); var defaultOptions = new ExecutionDataflowBlockOptions(); var dopOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; var mptOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, MaxMessagesPerTask = 10 }; var cancellationOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, MaxMessagesPerTask = 100, CancellationToken = cancellationSource.Token }; Assert.True(FeedTarget(actionBlockFactory, defaultOptions, 1, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, defaultOptions, 10, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, dopOptions, 1000, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, mptOptions, 10000, Intervention.None, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, mptOptions, 10000, Intervention.Complete, null, feedMethod, true)); Assert.True(FeedTarget(actionBlockFactory, cancellationOptions, 10000, Intervention.Cancel, cancellationSource, feedMethod, true)); } // Test scheduler usage { bool localPassed = true; var sts = new SimpleTaskScheduler(); var ab = new ActionBlock<int>(i => { localPassed &= TaskScheduler.Current.Id == sts.Id; return Task.Factory.StartNew(() => { }); }, new ExecutionDataflowBlockOptions { TaskScheduler = sts, MaxDegreeOfParallelism = -1, MaxMessagesPerTask = 10 }); for (int i = 0; i < 2; i++) ab.Post(i); ab.Complete(); ab.Completion.Wait(); Assert.True(localPassed, string.Format("{0}: Correct scheduler usage", localPassed ? "Success" : "Failure")); } // Test count { bool localPassed = true; var barrier1 = new Barrier(2); var barrier2 = new Barrier(2); var ab = new ActionBlock<int>(i => Task.Factory.StartNew(() => { barrier1.SignalAndWait(); barrier2.SignalAndWait(); })); for (int iter = 0; iter < 2; iter++) { for (int i = 1; i <= 2; i++) ab.Post(i); for (int i = 1; i >= 0; i--) { barrier1.SignalAndWait(); localPassed &= i == ab.InputCount; barrier2.SignalAndWait(); } } Assert.True(localPassed, string.Format("{0}: InputCount", localPassed ? "Success" : "Failure")); } // Test ordering { bool localPassed = true; int prev = -1; var ab = new ActionBlock<int>(i => { return Task.Factory.StartNew(() => { if (prev + 1 != i) localPassed &= false; prev = i; }); }); for (int i = 0; i < 2; i++) ab.Post(i); ab.Complete(); ab.Completion.Wait(); Assert.True(localPassed, string.Format("{0}: Correct ordering", localPassed ? "Success" : "Failure")); } // Test non-greedy { bool localPassed = true; var barrier = new Barrier(2); var ab = new ActionBlock<int>(i => { return Task.Factory.StartNew(() => { barrier.SignalAndWait(); }); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 }); ab.SendAsync(1); Task.Delay(200).Wait(); var sa2 = ab.SendAsync(2); localPassed &= !sa2.IsCompleted; barrier.SignalAndWait(); // for SendAsync(1) barrier.SignalAndWait(); // for SendAsync(2) localPassed &= sa2.Wait(100); int total = 0; ab = new ActionBlock<int>(i => { return Task.Factory.StartNew(() => { Interlocked.Add(ref total, i); Task.Delay(1).Wait(); }); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 }); for (int i = 1; i <= 100; i++) ab.SendAsync(i); SpinWait.SpinUntil(() => total == ((100 * 101) / 2), 30000); localPassed &= total == ((100 * 101) / 2); Assert.True(localPassed, string.Format("total={0} (must be {1})", total, (100 * 101) / 2)); Assert.True(localPassed, string.Format("{0}: Non-greedy support", localPassed ? "Success" : "Failure")); } // Test that OperationCanceledExceptions are ignored { bool localPassed = true; int sumOfOdds = 0; var ab = new ActionBlock<int>(i => { if ((i % 2) == 0) throw new OperationCanceledException(); return Task.Factory.StartNew(() => { sumOfOdds += i; }); }); for (int i = 0; i < 4; i++) ab.Post(i); ab.Complete(); ab.Completion.Wait(); localPassed = sumOfOdds == (1 + 3); Assert.True(localPassed, string.Format("{0}: OperationCanceledExceptions are ignored", localPassed ? "Success" : "Failure")); } // Test that null task is ignored { bool localPassed = true; int sumOfOdds = 0; var ab = new ActionBlock<int>(i => { if ((i % 2) == 0) return null; return Task.Factory.StartNew(() => { sumOfOdds += i; }); }); for (int i = 0; i < 4; i++) ab.Post(i); ab.Complete(); ab.Completion.Wait(); localPassed = sumOfOdds == (1 + 3); Assert.True(localPassed, string.Format("{0}: null tasks are ignored", localPassed ? "Success" : "Failure")); } // Test faulting from the delegate { bool localPassed = true; var ab = new ActionBlock<int>(new Func<int, Task>(i => { throw new InvalidOperationException(); })); ab.Post(42); ab.Post(1); ab.Post(2); ab.Post(3); try { localPassed &= ab.Completion.Wait(100); } catch { } localPassed &= ab.Completion.IsFaulted; localPassed &= SpinWait.SpinUntil(() => ab.InputCount == 0, 500); localPassed &= ab.Post(4) == false; Assert.True(localPassed, string.Format("{0}: Faulted from delegate handled correctly", localPassed ? "Success" : "Failure")); } // Test faulting from the task { bool localPassed = true; var ab = new ActionBlock<int>(i => Task.Factory.StartNew(() => { throw new InvalidOperationException(); })); ab.Post(42); ab.Post(1); ab.Post(2); ab.Post(3); try { localPassed &= ab.Completion.Wait(100); } catch { } localPassed &= ab.Completion.IsFaulted; localPassed &= SpinWait.SpinUntil(() => ab.InputCount == 0, 500); localPassed &= ab.Post(4) == false; Assert.True(localPassed, string.Format("{0}: Faulted from task handled correctly", localPassed ? "Success" : "Failure")); } }
internal AddTaskEvent(SimpleTaskScheduler scheduler, Task taskToBeAdded) { this.scheduler = scheduler; this.taskToBeAdded = taskToBeAdded; }