Beispiel #1
0
        public async Task AsyncLock_CancelledLock_LeavesLockUnlocked()
        {
            AsyncLock mutex = new AsyncLock();
            CancellationTokenSource       cts       = new CancellationTokenSource();
            TaskCompletionSource <object> taskReady = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();

            IDisposable unlock = await mutex.LockAsync();

            Task task = Task.Run(async() =>
            {
                AwaitableDisposable <IDisposable> lockTask = mutex.LockAsync(cts.Token);
                taskReady.SetResult(null);
                await lockTask;
            });
            await taskReady.Task;

            cts.Cancel();
            await AsyncAssert.ThrowsAsync <OperationCanceledException>(task).ConfigureAwait(false);

            Assert.True(task.IsCanceled);
            unlock.Dispose();

            AwaitableDisposable <IDisposable> finalLockTask = mutex.LockAsync();
            await finalLockTask;
        }
        public async Task Unlocked_PermitsLock()
        {
            AsyncMonitor monitor = new AsyncMonitor();

            AwaitableDisposable <IDisposable> task = monitor.EnterAsync();
            await task;
        }
Beispiel #3
0
        public void AsyncLock_PreCancelled_Locked_SynchronouslyCancels()
        {
            AsyncLock mutex = new AsyncLock();
            AwaitableDisposable <IDisposable> lockTask = mutex.LockAsync();
            CancellationToken token = new CancellationToken(true);

            Task <IDisposable> task = mutex.LockAsync(token).AsTask();

            Assert.True(task.IsCompleted);
            Assert.True(task.IsCanceled);
            Assert.False(task.IsFaulted);
        }
        /// <summary>
        /// Start the next available G/M/T-code and wait until this code may finish
        /// </summary>
        /// <returns>Awaitable disposable</returns>
        private AwaitableDisposable <IDisposable> WaitForFinish()
        {
            if (!Flags.HasFlag(CodeFlags.Unbuffered))
            {
                StartNextCode();
            }

            if (Interception.IsInterceptingConnection(SourceConnection))
            {
                return(new AwaitableDisposable <IDisposable>(Task.FromResult <IDisposable>(null)));
            }

            AwaitableDisposable <IDisposable> finishTask = (Macro == null) ? _codeFinishLocks[(int)Channel, (int)_codeType].LockAsync(CancellationToken) : Macro.WaitForCodeFinish();

            return(finishTask);
        }
        public async Task PulseAll_ReleasesAllWaiters()
        {
            AsyncMonitor monitor = new AsyncMonitor();

            int[] completed = { 0 };
            TaskCompletionSource <object> task1Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            Task waitTask1 = null;
            Task task1     = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask1 = monitor.WaitAsync();
                    task1Ready.SetResult(null);
                    await waitTask1;
                    Interlocked.Increment(ref completed[0]);
                }
            });
            await task1Ready.Task;
            Task waitTask2 = null;
            Task task2     = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask2 = monitor.WaitAsync();
                    task2Ready.SetResult(null);
                    await waitTask2;
                    Interlocked.Increment(ref completed[0]);
                }
            });
            await task2Ready.Task;

            AwaitableDisposable <IDisposable> lockTask3 = monitor.EnterAsync();

            using (await lockTask3)
            {
                monitor.PulseAll();
            }
            await Task.WhenAll(task1, task2).ConfigureAwait(false);

            int result = Interlocked.CompareExchange(ref completed[0], 0, 0);

            Assert.Equal(2, result);
        }
Beispiel #6
0
        public async Task AsyncLock_Locked_OnlyPermitsOneLockerAtATime()
        {
            AsyncLock mutex = new AsyncLock();
            TaskCompletionSource <object> task1HasLock  = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task1Continue = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2Ready    = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2HasLock  = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2Continue = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();

            Task task1 = Task.Run(async() =>
            {
                using (await mutex.LockAsync())
                {
                    task1HasLock.SetResult(null);
                    await task1Continue.Task;
                }
            });
            await task1HasLock.Task;

            Task task2 = Task.Run(async() =>
            {
                AwaitableDisposable <IDisposable> key = mutex.LockAsync();
                task2Ready.SetResult(null);
                using (await key)
                {
                    task2HasLock.SetResult(null);
                    await task2Continue.Task;
                }
            });
            await task2Ready.Task;

            Task task3 = Task.Run(async() => await mutex.LockAsync());

            task1Continue.SetResult(null);
            await task2HasLock.Task;

            Assert.False(task3.IsCompleted);
            task2Continue.SetResult(null);
            await task2;
            await task3;
        }
Beispiel #7
0
 public static ConfiguredTaskAwaitable <TResult> AnyContext <TResult>(this AwaitableDisposable <TResult> task) where TResult : IDisposable
 {
     return(task.ConfigureAwait(continueOnCapturedContext: false));
 }
 /// <summary>
 /// Configures the await to not attempt to marshal the continuation back to the original context captured.
 /// </summary>
 /// <typeparam name="T">The type of the result of the underlying task.</typeparam>
 /// <param name="awaitable">The awaitable to configure the await for.</param>
 /// <returns>
 /// An object used to await this awaitable.
 /// </returns>
 /// <remarks>
 /// This method makes it so that the code after the await can be ran on any available thread pool thread
 /// instead of being marshalled back to the same thread that the code was running on before the await.
 /// Avoiding this marshalling helps to slightly improve performance and helps avoid potential deadlocks. See
 /// <see href="http://blog.ciber.no/2014/05/19/using-task-configureawaitfalse-to-prevent-deadlocks-in-async-code/">
 /// this link</see> for more information.
 /// </remarks>
 public static ConfiguredTaskAwaitable <T> DontMarshallContext <T>(this AwaitableDisposable <T> awaitable)
     where T : IDisposable
 => awaitable.ConfigureAwait(false);