public Task PulseAllAsync() { TaskCompletionSourceWithoutInlining <EmptyStruct>?tcs = null; lock (this.syncObject) { // Atomically replace the completion source with a new, uncompleted source // while capturing the previous one so we can complete it. // This ensures that we don't leave a gap in time where WaitAsync() will // continue to return completed Tasks due to a Pulse method which should // execute instantaneously. tcs = this.taskCompletionSource; this.taskCompletionSource = this.CreateTaskSource(); this.isSet = false; } // Snap the Task that is exposed to the outside so we return that one. // Once we complete the TaskCompletionSourceWithoutInlinining's task, // the Task property will return the inner Task. // PulseAllAsync should return the same Task that WaitAsync callers would have observed previously. Task result = tcs.Task; tcs.TrySetResult(default(EmptyStruct)); return(result); }
public Task SetAsync() { TaskCompletionSourceWithoutInlining <EmptyStruct>?tcs = null; bool transitionRequired = false; lock (this.syncObject) { transitionRequired = !this.isSet; tcs = this.taskCompletionSource; this.isSet = true; } // Snap the Task that is exposed to the outside so we return that one. // Once we complete the TaskCompletionSourceWithoutInlinining's task, // the Task property will return the inner Task. // SetAsync should return the same Task that WaitAsync callers would have observed previously. Task result = tcs.Task; if (transitionRequired) { tcs.TrySetResult(default(EmptyStruct)); } return(result); }
/// <summary> /// Resets this event to a state that will block callers of <see cref="WaitAsync"/>. /// </summary> public void Reset() { lock (this.syncObject) { if (this.isSet) { this.taskCompletionSource = this.CreateTaskSource(); this.isSet = false; } } }
/// <summary> /// Initializes a new instance of the <see cref="AsyncManualResetEvent"/> class. /// </summary> /// <param name="initialState">A value indicating whether the event should be initially signaled.</param> /// <param name="allowInliningAwaiters"> /// A value indicating whether to allow <see cref="WaitAsync()"/> callers' continuations to execute /// on the thread that calls <see cref="SetAsync()"/> before the call returns. /// <see cref="SetAsync()"/> callers should not hold private locks if this value is <c>true</c> to avoid deadlocks. /// When <c>false</c>, the task returned from <see cref="WaitAsync()"/> may not have fully transitioned to /// its completed state by the time <see cref="SetAsync()"/> returns to its caller. /// </param> public AsyncManualResetEvent(bool initialState = false, bool allowInliningAwaiters = false) { this.allowInliningAwaiters = allowInliningAwaiters; this.taskCompletionSource = this.CreateTaskSource(); this.isSet = initialState; if (initialState) { this.taskCompletionSource.SetResult(EmptyStruct.Instance); } }
/// <summary> /// Initializes a new instance of the <see cref="AsyncManualResetEvent"/> class. /// </summary> /// <param name="initialState">A value indicating whether the event should be initially signaled.</param> /// <param name="allowInliningAwaiters"> /// A value indicating whether to allow <see cref="WaitAsync"/> callers' continuations to execute /// on the thread that calls <see cref="SetAsync()"/> before the call returns. /// <see cref="SetAsync()"/> callers should not hold private locks if this value is <c>true</c> to avoid deadlocks. /// When <c>false</c>, the task returned from <see cref="WaitAsync"/> may not have fully transitioned to /// its completed state by the time <see cref="SetAsync()"/> returns to its caller. /// </param> public AsyncManualResetEvent(bool initialState = false, bool allowInliningAwaiters = false) { this.allowInliningAwaiters = allowInliningAwaiters; this.taskCompletionSource = this.CreateTaskSource(); this.isSet = initialState; if (initialState) { // Complete the task immediately. We upcast first so that // the task always completes immediately rather than sometimes // being pushed to another thread and completed asynchronously // on .NET 4.5. TaskCompletionSource <EmptyStruct> tcs = this.taskCompletionSource; tcs.SetResult(EmptyStruct.Instance); } }
public Task PulseAllAsync() { TaskCompletionSourceWithoutInlining <EmptyStruct> tcs = null; lock (this.syncObject) { // Atomically replace the completion source with a new, uncompleted source // while capturing the previous one so we can complete it. // This ensures that we don't leave a gap in time where WaitAsync() will // continue to return completed Tasks due to a Pulse method which should // execute instantaneously. tcs = this.taskCompletionSource; this.taskCompletionSource = this.CreateTaskSource(); this.isSet = false; } tcs.TrySetResultToDefault(); return(tcs.Task); }
public Task SetAsync() { TaskCompletionSourceWithoutInlining <EmptyStruct> tcs = null; bool transitionRequired = false; lock (this.syncObject) { transitionRequired = !this.isSet; tcs = this.taskCompletionSource; this.isSet = true; } if (transitionRequired) { tcs.TrySetResultToDefault(); } return(tcs.Task); }
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)); }