public Task <Int32> WriteAsync(Func <Int32> action)
        {
            if (_isDisposed)
            {
                return(TaskEx.FromResult(0));
            }

            lock (_lockObj)
            {
                if (_writerCount > 0 || _readerCount > 0 || _waiterCount > 0)
                {
                    _waiterCount++;
                    var waiter = new AsyncWaiter <Int32>(action, WorkerTypes.Writer);
                    _waiters.Enqueue(waiter);
                    return(waiter);
                }

                _writerCount++;
            }

            try
            {
                var res = action();
                return(TaskEx.FromResult(res));
            }
            finally
            {
                EndWriterImpl();
            }
        }
        public Task <TResult> ReadAsync <TParam1, TResult>(TParam1 p1, Func <TParam1, TResult> action)
        {
            if (_isDisposed)
            {
                return(TaskEx.FromResult(default(TResult) !));
            }

            lock (_lockObj)
            {
                if (_writerCount > 0 || _waiterCount > 0)
                {
                    _waiterCount++;
                    var waiter = new AsyncWaiter <TParam1, TResult>(p1, action, WorkerTypes.Reader);
                    _waiters.Enqueue(waiter);
                    return(waiter);
                }

                _readerCount++;
            }

            try
            {
                var res = action(p1);
                return(TaskEx.FromResult(res));
            }
            finally
            {
                EndReaderImpl(action);
            }
        }
        public Task WriteAsync(Func <Task> asyncAction)
        {
            if (_isDisposed)
            {
                return(TaskEx.CompletedTask);
            }

            lock (_lockObj)
            {
                if (_writerCount > 0 || _readerCount > 0 || _waiterCount > 0)
                {
                    _waiterCount++;
                    var waiter = new AsyncWaiter <Task>(
                        asyncAction, WorkerTypes.Writer);
                    _waiters.Enqueue(waiter);
                    return(waiter);
                }

                _writerCount++;
            }

            try
            {
                var res = asyncAction();
                return(res);
            }
            finally
            {
                EndWriterImpl();
            }
        }
Esempio n. 4
0
        private void CancelAsync(AsyncWaiter waiter)
        {
            VerboseLog("{0:000}|{1}|async wait cancelled", Thread.CurrentThread.Id, _id);

            if (_asyncWaiters.Remove(waiter))
            {
                CleanUpWaiter(waiter);
            }
            waiter.Task.TrySetCanceled();
        }
Esempio n. 5
0
        private void TimeoutAsync(AsyncWaiter waiter)
        {
            if (waiter.CancelDelay.IsCancellationRequested)
            {
                return;
            }
            VerboseLog("{0:000}|{1}|async wait timed out", Thread.CurrentThread.Id, _id);

            if (_asyncWaiters.Remove(waiter))
            {
                CleanUpWaiter(waiter);
            }

            waiter.Task.TrySetResult(false);
        }
Esempio n. 6
0
        /// <summary>
        /// Will set ObjectedDisposedException is we were disposed.
        /// </summary>
        private void CleanUpWaiter(AsyncWaiter waiter)
        {
            waiter.CancelRegistration.Dispose();

            if (waiter.Delay != null)
            {
                waiter.CancelDelay.Cancel();
                waiter.Delay.Dispose();
            }

            if (_wasDisposed)
            {
                VerboseLog("{0:000}|{1}|disposing async waiter: {2}", Thread.CurrentThread.Id, _id, waiter.Task.Task.Id);
                waiter.Task.TrySetException(new ObjectDisposedException(GetType().Name));
            }
        }
        public async IAsyncEnumerable <TResult> ReadManyAsync <TParam, TResult>(
            TParam p1,
            Func <TParam, IAsyncEnumerable <TResult> > action)
        {
            Task waitFor;

            if (_isDisposed)
            {
                yield break;
            }

            lock (_lockObj)
            {
                if (_writerCount > 0 || _waiterCount > 0)
                {
                    _waiterCount++;
                    var waiter = new AsyncWaiter <Boolean>(() => true, WorkerTypes.IteratorReader);
                    _waiters.Enqueue(waiter);
                    waitFor = waiter;
                }
                else
                {
                    waitFor = TaskEx.CompletedTask;
                    _readerCount++;
                }
            }

            await waitFor;

            try
            {
                await foreach (var a in action(p1))
                {
                    if (_isDisposed)
                    {
                        yield break;
                    }
                    yield return(a);
                }
            }
            finally
            {
                EndReaderImpl(action);
            }
        }
        private Task WaitForIteratorAsync()
        {
            Task waitFor;

            lock (_lockObj)
            {
                if (_writerCount > 0 || _waiterCount > 0)
                {
                    _waiterCount++;
                    var waiter = new AsyncWaiter <Boolean>(() => true, WorkerTypes.IteratorReader);
                    _waiters.Enqueue(waiter);
                    waitFor = waiter;
                }
                else
                {
                    waitFor = TaskEx.CompletedTask;
                    _readerCount++;
                }
            }

            return(waitFor);
        }
Esempio n. 9
0
        public Task <bool> WaitAsync(Int32 duration, CancellationToken token)
        {
            VerboseLog("{0:000}|{1}|async wait requested", Thread.CurrentThread.Id, _id);

            CheckDisposed();
            token.ThrowIfCancellationRequested();

            if (_sem.TryAcquire())
            {
                VerboseLog("{0:000}|{1}|async wait immediate success", Thread.CurrentThread.Id, _id);
                return(Task.FromResult(true));
            }


            if (duration == 0)
            {
                return(Task.FromResult(false));
            }

            if (_asyncWaiters == null)
            {
                lock (this)
                {
                    if (_asyncWaiters == null)
                    {
                        _asyncWaiters = new ConcurrentLinkedQueue <AsyncWaiter>();
                    }
                }
            }

            AsyncWaiter waiter = new AsyncWaiter();
            TaskCompletionSource <bool> task = new TaskCompletionSource <bool>();

            waiter.Task = task;

            if (duration != -1)
            {
                waiter.CancelDelay = new CancellationTokenSource();
                waiter.Delay       = Task.Delay(duration, waiter.CancelDelay.Token);
                waiter.Delay.ContinueWith(new ActionContinuation(() => TimeoutAsync(waiter)));
            }

            if (token != CancellationToken.None)
            {
                waiter.CancelRegistration = token.Register(() => CancelAsync(waiter));
            }

            _asyncWaiters.Add(waiter);

            VerboseLog("{0:000}|{1}|async wait enqued: {2:X}; {3}", Thread.CurrentThread.Id, _id, waiter.GetHashCode(), waiter.Task.Task.Id);

            if (_wasDisposed || token.IsCancellationRequested || waiter.Delay != null && waiter.Delay.IsCompleted)
            {
                // Mitigate the above race where a finishing condition occured
                // before where able to add our waiter to the waiters list.
                if (_asyncWaiters.Remove(waiter))
                {
                    CleanUpWaiter(waiter);
                }
            }

            return(task.Task);
        }