Ejemplo n.º 1
0
        public void CancelStressTest()
        {
            foreach (bool sync in new[] { false, true })
            {
                const int N       = 64;
                long      counter = 0;
                var       mutex   = new AsyncMutex();
                Task[]    tasks   = Enumerable.Range(0, N).Select(_ => Inc()).ToArray();
                Task.WaitAll(tasks);
                Assert.AreEqual(N, counter);

                async Task Inc()
                {
                    while (true)
                    {
                        using (var cancel = new CancellationTokenSource()) {
                            Task t = mutex.LockAsync(cancel.Token);
                            await Task.Yield();

                            cancel.Cancel();
                            if (!t.IsCanceled)
                            {
                                await t;
                                break;
                            }
                        }
                    }
                    long next = counter + 1;
                    await Task.Yield();

                    counter = next;
                    mutex.Unlock(runNextSynchronously: sync);
                }
            }
        }
Ejemplo n.º 2
0
        public async Task LockAsync()
        {
            var mutex = new AsyncMutex();
            await mutex.LockAsync();

            mutex.Unlock();
        }
Ejemplo n.º 3
0
        public void Lock()
        {
            var mutex = new AsyncMutex();

            mutex.Lock();
            mutex.Unlock();
        }
Ejemplo n.º 4
0
        public void CancelTest()
        {
            var mutex = new AsyncMutex();

            using (var cancel = new CancellationTokenSource()) {
                mutex.LockAsync().Wait();
                Task t = mutex.LockAsync(cancel.Token);
                Assert.IsFalse(t.IsCompleted);
                mutex.Unlock(runNextSynchronously: true);
                t.Wait();

                t = mutex.LockAsync(cancel.Token);
                cancel.Cancel();
                Assert.AreEqual(TaskStatus.Canceled, t.Status);

                mutex.Unlock(runNextSynchronously: true);
                t = mutex.LockAsync(cancel.Token);
                Assert.AreEqual(TaskStatus.RanToCompletion, t.Status);
            }
        }
Ejemplo n.º 5
0
        public void ExampleTest()
        {
            var expected = new[] {
                "Worker #0: 0",
                "Worker #1: 0",
                "Worker #1: 1",
                "Worker #1: 2",
                "Worker #0: 1",
                "Worker #0: 2",
            };

            CollectionAssert.AreEqual(expected, Example().Result);

            async Task <List <string> > Example()
            {
                var res   = new List <string>();
                var mutex = new AsyncMutex();
                await mutex.LockAsync();

                Task[] tasks = Enumerable.Range(0, 2).Select(Work).ToArray();
                mutex.Unlock(runNextSynchronously: true);
                await Task.WhenAll(tasks);

                return(res);

                async Task Work(int worker)
                {
                    for (int i = 0; i != 3; ++i)
                    {
                        await mutex.LockAsync();

                        res.Add($"Worker #{worker}: {i}");
                        mutex.Unlock(runNextSynchronously: true);
                    }
                }
            }
        }
Ejemplo n.º 6
0
 public void FairnessTest()
 {
     foreach (bool sync in new[] { false, true })
     {
         var mutex = new AsyncMutex();
         var tasks = new Queue <Task>(Enumerable.Range(0, 1024).Select(_ => mutex.LockAsync()));
         while (tasks.Count > 0)
         {
             tasks.Enqueue(mutex.LockAsync());
             for (int i = 0; i != 2; ++i)
             {
                 tasks.Dequeue().Wait();
                 mutex.Unlock(sync);
             }
         }
     }
 }
Ejemplo n.º 7
0
        public async Task MutualExclusion()
        {
            int sharedValue  = 0;
            var mutex        = new AsyncMutex();
            var hundredEvent = new AsyncManualResetEvent();

            // Create 10 threads that increment a value 10 times each
            for (int n = 0; n < 10; n++)
            {
                new Thread(async() =>
                {
                    await mutex.Lock();

                    int privateValue = sharedValue;
                    for (int m = 0; m < 10; m++)
                    {
                        // If the mutex works, no other thread will increment sharedValue
                        sharedValue++;
                        privateValue++;
                        Assert.Equal(privateValue, sharedValue);

                        if (sharedValue == 100)
                        {
                            // The test case is complete
                            hundredEvent.Set();
                        }

                        // Yield the CPU to give other threads a chance to run
                        await Task.Delay(10);
                    }

                    mutex.Unlock();
                }).Start();
            }

            await hundredEvent.WaitAsync();

            Assert.Equal(100, sharedValue);
        }
Ejemplo n.º 8
0
        public void LockUnlockStressTest()
        {
            foreach (bool sync in new[] { false, true })
            {
                const int N       = 64 << 10;
                long      counter = 0;
                var       mutex   = new AsyncMutex();
                Task.WhenAll(Enumerable.Range(0, N).Select(_ => Inc())).Wait();
                Assert.AreEqual(N, counter);

                async Task Inc()
                {
                    await mutex.LockAsync();

                    await Task.Yield();

                    long next = counter + 1;
                    await Task.Yield();

                    counter = next;
                    mutex.Unlock(runNextSynchronously: sync);
                }
            }
        }
Ejemplo n.º 9
0
        public void LockUnlockBenchmark()
        {
            using (var cancel = new CancellationTokenSource()) {
                Console.WriteLine("Warmup:");
                Benchmark(runNextSynchronously: false, cancelable: false, threads: 1024).Wait();
                Benchmark(runNextSynchronously: false, cancelable: true, threads: 1024).Wait();
                Benchmark(runNextSynchronously: true, cancelable: false, threads: 1024).Wait();
                Benchmark(runNextSynchronously: true, cancelable: true, threads: 1024).Wait();

                Console.WriteLine("\nThe real thing:");
                foreach (bool sync in new[] { true, false })
                {
                    foreach (bool c in new[] { false, true })
                    {
                        foreach (int threads in new[] { 1, 2, 4, 32, 1024 })
                        {
                            Benchmark(runNextSynchronously: sync, cancelable: c, threads: threads).Wait();
                        }
                    }
                }

                async Task Benchmark(bool runNextSynchronously, bool cancelable, int threads)
                {
                    long      counter   = 0;
                    var       mutex     = new AsyncMutex();
                    TimeSpan  duration  = TimeSpan.FromSeconds(1);
                    Stopwatch stopwatch = Stopwatch.StartNew();
                    await Task.WhenAll(Enumerable.Range(0, threads).Select(_ => Inc()));

                    double ns = 1e9 * stopwatch.Elapsed.TotalSeconds / counter;

                    Console.WriteLine(
                        "  Benchmark(runNextSynchronously: {0,5}, cancelable: {1,5}, threads: {2,5:N0}): {3,7:N1} ns/call",
                        runNextSynchronously, cancelable, threads, ns);

                    async Task Inc()
                    {
                        await Task.Yield();

                        while (stopwatch.Elapsed < duration)
                        {
                            if (cancelable)
                            {
                                for (int i = 0; i != 64; ++i)
                                {
                                    await mutex.LockAsync(cancel.Token);

                                    ++counter;
                                    mutex.Unlock(runNextSynchronously: runNextSynchronously);
                                }
                            }
                            else
                            {
                                for (int i = 0; i != 64; ++i)
                                {
                                    await mutex.LockAsync();

                                    ++counter;
                                    mutex.Unlock(runNextSynchronously: runNextSynchronously);
                                }
                            }
                        }
                    }
                }
            }
        }