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); }