/// <summary>Returns an already completed, new mutex instance</summary>
        private static AsyncCancelableMutex CreateAlreadyDone()
        {
            var mtx = new AsyncCancelableMutex(CancellationToken.None);

            mtx.Set(async: false);
            return(mtx);
        }
 /// <summary>Delcare the producer as beeing blocked on a full queue</summary>
 /// <param name="ct"></param>
 /// <returns></returns>
 protected Task MarkProducerAsBlocked_NeedsLocking(CancellationToken ct)
 {
     if (ct.IsCancellationRequested)
     {
         return(Task.FromCanceled(ct));
     }
     if (m_producerLock.IsCompleted)
     {
         m_producerLock = new AsyncCancelableMutex(ct);
     }
     LogProducer("blocked on full");
     return(m_producerLock.Task);
 }
        private Task WaitForNextItem_NeedsLocking(CancellationToken ct)
        {
            if (m_done)
            {
                return(Task.CompletedTask);
            }

            Contract.Requires(m_blockedConsumer == null || m_blockedConsumer.Task.IsCompleted);

            var waiter = new AsyncCancelableMutex(ct);

            m_blockedConsumer = waiter;
            return(waiter.Task);
        }
        public async Task OnNextAsync(TInput value, CancellationToken ct)
        {
            while (!ct.IsCancellationRequested)
            {
                AsyncCancelableMutex waiter;
                lock (m_lock)
                {
                    if (m_done)
                    {
                        throw new InvalidOperationException("Cannot post more values after calling Complete()");
                    }

                    if (m_queue.Count < m_capacity)
                    {
                        var t = Task.Factory.StartNew(
                            s_processItemHandler,
                            Tuple.Create(this, value, ct),
                            ct,
                            TaskCreationOptions.PreferFairness,
                            m_scheduler
                            ).Unwrap();

                        m_queue.Enqueue(t);

                        var _ = t.ContinueWith((_t) =>
                        {
                            lock (m_lock)
                            {
                                // we should only wake up the consumers if we are the fist in the queue !
                                if (m_queue.Count > 0 && m_queue.Peek() == _t)
                                {
                                    WakeUpConsumer_NeedLocking();
                                }
                            }
                        }, TaskContinuationOptions.ExecuteSynchronously);

                        return;
                    }

                    // no luck, we need to wait for the queue to become non-full
                    waiter            = new AsyncCancelableMutex(ct);
                    m_blockedProducer = waiter;
                }

                await waiter.Task.ConfigureAwait(false);
            }

            ct.ThrowIfCancellationRequested();
        }
        protected Task MarkConsumerAsAwaitingCompletion_NeedsLocking(CancellationToken ct)
        {
            Contract.Debug.Requires(m_mode == AsyncOrderingMode.CompletionOrder);

            var cl = m_completionLock;

            if (cl.IsCompleted)
            {
                LogConsumer("Creating new task completion lock");
                cl = new AsyncCancelableMutex(ct);
                m_completionLock = cl;
            }
            LogConsumer("marked as waiting for task completion");
            return(cl.Task);
        }
 private static void CancelDefered(AsyncCancelableMutex mutex)
 {
     ThreadPool.QueueUserWorkItem((state) => ((AsyncCancelableMutex)state).TrySetCanceled(), mutex);
 }
 private static void SetDefered(AsyncCancelableMutex mutex)
 {
     ThreadPool.QueueUserWorkItem((state) => ((AsyncCancelableMutex)state).TrySetResult(null), mutex);
 }