Exemplo n.º 1
0
        private bool TryComplete(Exception error = null)
        {
            bool completeTask;

            lock (SyncObj)
            {
                AssertInvariants();

                // If we've already marked the channel as completed, bail.
                if (_doneWriting != null)
                {
                    return(false);
                }

                // Mark that we're done writing.
                _doneWriting = error ?? ChannelUtilities.DoneWritingSentinel;
                completeTask = _items.IsEmpty;
            }

            // If there are no items in the queue, complete the channel's task,
            // as no more data can possibly arrive at this point.  We do this outside
            // of the lock in case we'll be running synchronous completions, and we
            // do it before completing blocked/waiting readers, so that when they
            // wake up they'll see the task as being completed.
            if (completeTask)
            {
                ChannelUtilities.Complete(_completion, error);
            }

            // At this point, _blockedReaders/Writers and _waitingReaders/Writers will not be mutated:
            // they're only mutated by readers/writers while holding the lock, and only if _doneWriting is null.
            // We also know that only one thread (this one) will ever get here, as only that thread
            // will be the one to transition from _doneWriting false to true.  As such, we can
            // freely manipulate _blockedReaders and _waitingReaders without any concurrency concerns.
            ChannelUtilities.FailInteractors <ReaderInteractor <T>, T>(_blockedReaders, error);
            ChannelUtilities.FailInteractors <WriterInteractor <T>, VoidResult>(_blockedWriters, error);
            ChannelUtilities.WakeUpWaiters(ref _waitingReaders, result: false);
            ChannelUtilities.WakeUpWaiters(ref _waitingWriters, result: false);

            // Successfully transitioned to completed.
            return(true);
        }
Exemplo n.º 2
0
        private bool TryComplete(Exception error = null)
        {
            lock (SyncObj)
            {
                AssertInvariants();

                // Mark the channel as being done. Since there's no buffered data, we can complete immediately.
                if (_completion.Task.IsCompleted)
                {
                    return(false);
                }
                ChannelUtilities.Complete(_completion, error);

                // Fail any blocked readers/writers, as there will be no writers/readers to pair them with.
                ChannelUtilities.FailInteractors <ReaderInteractor <T>, T>(_blockedReaders, ChannelUtilities.CreateInvalidCompletionException(error));
                ChannelUtilities.FailInteractors <WriterInteractor <T>, VoidResult>(_blockedWriters, ChannelUtilities.CreateInvalidCompletionException(error));

                // Let any waiting readers and writers know there won't be any more data
                ChannelUtilities.WakeUpWaiters(ref _waitingReaders, result: false, error: error);
                ChannelUtilities.WakeUpWaiters(ref _waitingWriters, result: false, error: error);
            }

            return(true);
        }