public Task WaitAsync(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled(cancellationToken));
            }

            lock (_signalAwaiters)
            {
                if (_signaled)
                {
                    _signaled = false;
                    return(Task.CompletedTask);
                }
                else
                {
                    var waiter = new WaiterCompletionSource(this, _allowInliningAwaiters, cancellationToken);
                    if (cancellationToken.IsCancellationRequested)
                    {
                        waiter.TrySetCanceled(cancellationToken);
                    }
                    else
                    {
                        _signalAwaiters.Enqueue(waiter);
                    }

                    return(waiter.Task);
                }
            }
        }
        /// <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);
                }
            }
        }
Esempio n. 3
0
        public ValueTask <AsyncLockObject> LockAsync(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(ValueTask.FromCanceled <AsyncLockObject>(cancellationToken));
            }

            lock (_signalAwaiters)
            {
                if (_signaled)
                {
                    _signaled = false;
                    return(new ValueTask <AsyncLockObject>(new AsyncLockObject(this)));
                }
                else
                {
                    var waiter = new WaiterCompletionSource(this, _allowInliningAwaiters, cancellationToken);
                    if (cancellationToken.IsCancellationRequested)
                    {
                        waiter.TrySetCanceled(cancellationToken);
                    }
                    else
                    {
                        _signalAwaiters.Enqueue(waiter);
                    }

                    return(new ValueTask <AsyncLockObject>(waiter.Task));
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Sets the signal if it has not already been set, allowing one awaiter to handle the signal if one is already waiting.
        /// </summary>
        public void Set()
        {
            WaiterCompletionSource toRelease = null;

            lock (this.signalAwaiters)
            {
                if (this.signalAwaiters.Count > 0)
                {
                    toRelease = this.signalAwaiters.Dequeue();
                }
                else if (!this.signaled)
                {
                    this.signaled = true;
                }
            }

            if (toRelease != null)
            {
                toRelease.Registration.Dispose();
                toRelease.TrySetResultToDefault();
            }
        }