Esempio n. 1
0
 /// <summary>
 /// Creates an async-compatible barrier.
 /// </summary>
 /// <param name="participants">The number of participants.</param>
 public AsyncBarrier(int participants)
 {
     _sync = new object();
     _tcs = new TaskCompletionSource();
     _participants = _count = participants;
     //Enlightenment.Trace.AsyncBarrier_PhaseChanged(this, 0, participants, _tcs.Task);
 }
Esempio n. 2
0
 /// <summary>
 /// Creates an async-compatible manual-reset event.
 /// </summary>
 /// <param name="set">Whether the manual-reset event is initially set or unset.</param>
 public AsyncManualResetEvent(bool set)
 {
     _sync = new object();
     _tcs = new TaskCompletionSource();
     if (set) {
         //Enlightenment.Trace.AsyncManualResetEvent_Set(this, _tcs.Task);
         _tcs.SetResult();
     }
 }
Esempio n. 3
0
 /// <summary>
 /// Returns a <see cref="Task"/> that is canceled when this <see cref="CancellationToken"/> is canceled. This method will leak resources if the cancellation token is long-lived; use <see cref="ToCancellationTokenTaskSource"/> for a similar approach with proper resource management.
 /// </summary>
 /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor.</param>
 /// <returns>A <see cref="Task"/> that is canceled when this <see cref="CancellationToken"/> is canceled.</returns>
 public static Task AsTask(this CancellationToken cancellationToken)
 {
     if (!cancellationToken.CanBeCanceled) {
         return TaskConstants.Never;
     }
     if (cancellationToken.IsCancellationRequested) {
         return TaskConstants.Canceled;
     }
     var tcs = new TaskCompletionSource();
     cancellationToken.Register(() => tcs.TrySetCanceled(), false);
     return tcs.Task;
 }
Esempio n. 4
0
 /// <summary>
 /// Creates a task for the specified cancellation token, registering with the token if necessary.
 /// </summary>
 /// <param name="cancellationToken">The cancellation token to observe.</param>
 public CancellationTokenTaskSource(CancellationToken cancellationToken)
 {
     if (!cancellationToken.CanBeCanceled) {
         Task = TaskConstants.Never;
         return;
     }
     if (cancellationToken.IsCancellationRequested) {
         Task = TaskConstants.Canceled;
         return;
     }
     var tcs = new TaskCompletionSource();
     _registration = cancellationToken.Register(() => tcs.TrySetCanceled(), false);
     Task = tcs.Task;
 }
Esempio n. 5
0
        /// <summary>
        /// Wraps a <see cref="WaitHandle"/> with a <see cref="Task{Boolean}"/>. If the <see cref="WaitHandle"/> is signalled, the returned task is completed with a <c>true</c> result. If the observation times out, the returned task is completed with a <c>false</c> result. If the observation is cancelled, the returned task is cancelled. If the handle is already signalled, the timeout is zero, or the cancellation token is already cancelled, then this method acts synchronously.
        /// </summary>
        /// <param name="handle">The <see cref="WaitHandle"/> to observe.</param>
        /// <param name="timeout">The timeout after which the <see cref="WaitHandle"/> is no longer observed.</param>
        /// <param name="token">The cancellation token that cancels observing the <see cref="WaitHandle"/>.</param>
        public static Task<bool> FromWaitHandle(WaitHandle handle, TimeSpan timeout, CancellationToken token)
        {
            // Handle synchronous cases.
            var alreadySignalled = handle.WaitOne(0);
            if (alreadySignalled) {
                return TaskConstants.BooleanTrue;
            }
            if (timeout == TimeSpan.Zero) {
                return TaskConstants.BooleanFalse;
            }
            if (token.IsCancellationRequested) {
                return TaskConstants<bool>.Canceled;
            }

            // Register all asynchronous cases.
            var tcs = new TaskCompletionSource<bool>();
            var threadPoolRegistration = ThreadPoolEnlightenment.RegisterWaitForSingleObject(handle, (state, timedOut) => ((TaskCompletionSource<bool>)state).TrySetResult(!timedOut), tcs, timeout);
            var tokenRegistration = token.Register(state => ((TaskCompletionSource<bool>)state).TrySetCanceled(), tcs, false);
            tcs.Task.ContinueWith(_ => {
                threadPoolRegistration.Dispose();
                tokenRegistration.Dispose();
            }, TaskScheduler.Default);
            return tcs.Task;
        }
Esempio n. 6
0
            /// <summary>
            /// Upgrades the reader lock to a writer lock. Returns a disposable that downgrades the writer lock to a reader lock when disposed.
            /// </summary>
            /// <param name="cancellationToken">The cancellation token used to cancel the upgrade. If this is already set, then this method will attempt to upgrade immediately (succeeding if the lock is currently available).</param>
            public AwaitableDisposable<IDisposable> UpgradeAsync(CancellationToken cancellationToken)
            {
                lock (_asyncReaderWriterLock.SyncObject) {
                    if (_upgrade != null) {
                        throw new InvalidOperationException("Cannot upgrade.");
                    }

                    _upgrade = _asyncReaderWriterLock.UpgradeAsync(cancellationToken);
                }

                _asyncReaderWriterLock.ReleaseWaitersWhenCanceled(_upgrade);
                var ret = new TaskCompletionSource<IDisposable>();
                _upgrade.ContinueWith(t => {
                    if (t.IsCanceled) {
                        lock (_asyncReaderWriterLock.SyncObject) {
                            _upgrade = null;
                        }
                    }
                    ret.TryCompleteFromCompletedTask(t);
                }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
                return new AwaitableDisposable<IDisposable>(ret.Task);
            }
Esempio n. 7
0
        /// <summary>
        /// Signals completions to this barrier. Returns the task for the current phase, which may already be completed. Returns <c>null</c> if the signal count is greater than the remaining participant count.
        /// </summary>
        /// <param name="signalCount">The number of completions to signal.</param>
        /// <param name="removeParticipants">Whether the participants should be removed permanently.</param>
        private Task SignalAsync(int signalCount, bool removeParticipants)
        {
            var oldTcs = _tcs;
            lock (_sync) {
                if (signalCount == 0) {
                    return _tcs.Task;
                }
                if (signalCount > _count) {
                    return null;
                }
                _count -= signalCount;
                //Enlightenment.Trace.AsyncBarrier_CountChanged(this, _phase, _count);
                if (removeParticipants) {
                    _participants -= signalCount;
                    //Enlightenment.Trace.AsyncBarrier_ParticipantsChanged(this, _phase, _participants);
                }

                if (_count == 0) {
                    // Start post-phase action; when it completes, move to the next phase.
                    RunPostPhaseActionAsync().ContinueWith(t => {
                        lock (_sync) {
                            _tcs = new TaskCompletionSource();
                            _count = _participants;
                            ++_phase;
                            //Enlightenment.Trace.AsyncBarrier_PhaseChanged(this, _phase, _participants, _tcs.Task);
                        }

                        // When the post-phase action completes, complete all waiting tasks for that phase, propagating the post-phase action result.
                        oldTcs.TryCompleteFromCompletedTask(t);
                    }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
                }
            }

            return oldTcs.Task;
        }
Esempio n. 8
0
 /// <summary>
 /// Wraps a begin/end asynchronous method.
 /// </summary>
 /// <param name="beginMethod">The begin method.</param>
 /// <param name="endMethod">The end method.</param>
 /// <returns></returns>
 public static Task FromApm(Func<AsyncCallback, object, IAsyncResult> beginMethod, Action<IAsyncResult> endMethod)
 {
     var tcs = new TaskCompletionSource<object>();
     beginMethod(Callback(endMethod, tcs), null);
     return tcs.Task;
 }
Esempio n. 9
0
 private static AsyncCallback Callback(Action<IAsyncResult> endMethod, TaskCompletionSource<object> tcs)
 {
     return asyncResult => {
         try {
             endMethod(asyncResult);
             tcs.TrySetResult(null);
         }
         catch (OperationCanceledException) {
             tcs.TrySetCanceled();
         }
         catch (Exception ex) {
             tcs.TrySetException(ex);
         }
     };
 }
Esempio n. 10
0
        /// <summary>
        /// Wraps a <see cref="Task"/> into the Begin method of an APM pattern.
        /// </summary>
        /// <param name="task">The task to wrap.</param>
        /// <param name="callback">The callback method passed into the Begin method of the APM pattern.</param>
        /// <param name="state">The state passed into the Begin method of the APM pattern.</param>
        /// <returns>The asynchronous operation, to be returned by the Begin method of the APM pattern.</returns>
        public static IAsyncResult ToBegin(Task task, AsyncCallback callback, object state)
        {
            var tcs = new TaskCompletionSource(state);
            task.ContinueWith(t => {
                tcs.TryCompleteFromCompletedTask(t);

                callback?.Invoke(tcs.Task);
            }, TaskScheduler.Default);

            return tcs.Task;
        }
Esempio n. 11
0
        /// <summary>
        /// Asynchronously waits for a signal on this condition variable. The associated lock MUST be held when calling this method, and it will still be held when this method returns, even if the method is cancelled.
        /// </summary>
        /// <param name="cancellationToken">The cancellation signal used to cancel this wait.</param>
        public Task WaitAsync(CancellationToken cancellationToken)
        {
            lock (_mutex) {
                // Begin waiting for either a signal or cancellation.
                var task = _queue.Enqueue(_mutex, cancellationToken);

                // Attach to the signal or cancellation.
                var retTcs = new TaskCompletionSource();
                task.ContinueWith(async t => {
                    // Re-take the lock.
                    await _asyncLock.LockAsync().ConfigureAwait(false);

                    // Propagate the cancellation exception if necessary.
                    retTcs.TryCompleteFromCompletedTask(t);
                }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

                var ret = retTcs.Task;
                //Enlightenment.Trace.AsyncConditionVariable_TrackWait(this, _asyncLock, task, ret);

                // Release the lock while we are waiting.
                _asyncLock.ReleaseLock();

                return ret;
            }
        }
Esempio n. 12
0
 /// <summary>
 /// Resets the event. If the event is already reset, this method does nothing.
 /// </summary>
 public void Reset()
 {
     lock (_sync) {
         if (_tcs.Task.IsCompleted) {
             _tcs = new TaskCompletionSource();
         }
         //Enlightenment.Trace.AsyncManualResetEvent_Reset(this, _tcs.Task);
     }
 }
Esempio n. 13
-1
 /// <summary>
 /// Creates an async-compatible countdown event.
 /// </summary>
 /// <param name="count">The number of signals this event will need before it becomes set. Must be greater than zero.</param>
 public AsyncCountdownEvent(int count)
 {
     _tcs = new TaskCompletionSource();
     _count = count;
     //Enlightenment.Trace.AsyncCountdownEvent_CountChanged(this, -1, count);
 }