/// <summary> /// Initializes a new instance of the <see cref="AsyncSemaphore"/> class. /// </summary> /// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently.</param> public AsyncSemaphore(int initialCount) { this.semaphore = new SemaphoreSlim(initialCount); this.uncontestedReleaser = Task.FromResult(new Releaser(this)); this.canceledReleaser = ThreadingTools.TaskFromCanceled <Releaser>(new CancellationToken(canceled: true)); }
/// <summary> /// Returns an awaitable that may be used to asynchronously acquire the next signal. /// </summary> /// <param name="cancellationToken">A token whose cancellation removes the caller from the queue of those waiting for the event.</param> /// <returns>An awaitable.</returns> public Task WaitAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(ThreadingTools.TaskFromCanceled(cancellationToken)); } lock (this.signalAwaiters) { if (this.signaled) { this.signaled = false; return(TplExtensions.CompletedTask); } else { var waiter = new WaiterCompletionSource(this, cancellationToken, this.allowInliningAwaiters); if (cancellationToken.IsCancellationRequested) { waiter.TrySetCanceled(cancellationToken); } else { this.signalAwaiters.Enqueue(waiter); } return(waiter.Task); } } }
/// <summary> /// Requests access to the lock. /// </summary> /// <param name="cancellationToken">A token whose cancellation signals lost interest in the lock.</param> /// <returns>A task whose result is a releaser that should be disposed to release the lock.</returns> public Task <Releaser> EnterAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return(ThreadingTools.TaskFromCanceled <Releaser>(cancellationToken)); } return(this.LockWaitingHelper(this.semaphore.WaitAsync(cancellationToken))); }
public Task SignalAndWaitAsync() { try { this.Signal(); return(this.WaitAsync()); } catch (Exception ex) { return(ThreadingTools.TaskFromException(ex)); } }
public Task <T> DequeueAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return(ThreadingTools.TaskFromCanceled <T>(cancellationToken)); } T result; lock (this.SyncRoot) { if (this.IsCompleted) { return(TplExtensions.CanceledTaskOfT <T>()); } if (this.queueElements?.Count > 0) { result = this.queueElements.Dequeue(); } else { if (this.dequeuingWaiters == null) { this.dequeuingWaiters = new Queue <TaskCompletionSource <T> >(capacity: 2); } else { this.FreeCanceledDequeuers(); } var waiterTcs = new TaskCompletionSourceWithoutInlining <T>(allowInliningContinuations: false); waiterTcs.AttachCancellation(cancellationToken, this); this.dequeuingWaiters.Enqueue(waiterTcs); return(waiterTcs.Task); } } this.CompleteIfNecessary(); return(Task.FromResult(result)); }
internal void TrySetCanceled(CancellationToken cancellationToken) { if (!this.Task.IsCompleted) { if (this.CanCompleteInline) { ThreadingTools.TrySetCanceled(this, cancellationToken); } else { Tuple <TaskCompletionSourceWithoutInlining <T>, CancellationToken> tuple = Tuple.Create(this, cancellationToken); ThreadPool.QueueUserWorkItem( state => { var s = (Tuple <TaskCompletionSourceWithoutInlining <T>, CancellationToken>)state; ThreadingTools.TrySetCanceled(s.Item1, s.Item2); }, tuple); } } }