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(); } }
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(); }
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); }
/// <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); }
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); }