Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
 /// <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;
         }
     }
 }
Beispiel #4
0
        /// <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);
            }
        }
Beispiel #5
0
        /// <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);
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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));
        }