/// <summary> /// WaitForIdle /// </summary> /// <param name="ctoken"></param> /// <returns></returns> public Task WaitForIdle(CancellationToken ctoken) { if (ctoken.IsCancellationRequested) { return(Tasks.FromException <bool>(new OperationCanceledException(ctoken))); } else { lock (syncRoot) { if (referenceCount == 0) { return(Task.FromResult(true)); } else { TaskCompletionSource <bool> k = new TaskCompletionSource <bool>(); Waiter waiter = new Waiter() { id = null, k = k, ctoken = ctoken, ctr = null, }; long id = waiters.Enqueue(waiter); waiter.id = id; Utils.PostRegistration(ctoken, ctr => SetRegistrationForWait(id, ctr), () => CancelWait(id)); return(k.Task); } } } }
public Task <Task> StartWorkItem(Func <int, Task> work, CancellationToken ctoken) { if (ctoken.IsCancellationRequested) { #if NET451 var tcs = new TaskCompletionSource <Task>(); tcs.SetException(new OperationCanceledException(ctoken)); return(tcs.Task); #else return(Task.FromException <Task>(new OperationCanceledException(ctoken))); #endif } else { lock (syncRoot) { if (idleWorkers.Count > 1) { return(Task.FromResult <Task>(StartWorker(work))); } else { TaskCompletionSource <Task> k = new TaskCompletionSource <Task>(); WaitingWorkItem wa = new WaitingWorkItem() { id = null, work = work, ctoken = ctoken, ctr = null, k = k }; long id = waitingWorkItems.Enqueue(wa); wa.id = id; Utils.PostRegistration(ctoken, ctr => SetRegistrationForWorkItem(id, ctr), () => CancelWorkItem(id)); return(k.Task); } } } }
/// <inheritdoc /> public Task <AcquireWriteResult> AcquireWriteAsync(int desiredSpace, CancellationToken ctoken) { if (desiredSpace < 1) { return(Task.FromResult <AcquireWriteResult>(new AcquireWriteFaulted(new ArgumentOutOfRangeException("desiredSpace", "Must be at least one")))); } if (ctoken.IsCancellationRequested) { return(Task.FromResult <AcquireWriteResult>(new AcquireWriteCancelled())); } else { lock (syncRoot) { if (eofSignaled) { return(Task.FromResult <AcquireWriteResult>(new AcquireWriteFaulted(new InvalidOperationException("Can't acquire for write after EOF has been signaled")))); } else if (!writeLocked.HasValue && (!capacity.HasValue || (capacity.Value - items.Count) >= desiredSpace)) { writeLocked = desiredSpace; return(Task.FromResult <AcquireWriteResult>(new AcquireWriteSucceeded(readPtr + items.Count, desiredSpace))); } else if (capacity.HasValue && desiredSpace > capacity.Value) { return(Task.FromResult <AcquireWriteResult>( new AcquireWriteFaulted(new InvalidOperationException("Attempting to acquire more space than will ever become available")))); } else { TaskCompletionSource <AcquireWriteResult> k = new TaskCompletionSource <AcquireWriteResult>(); WaitingWrite ww = new WaitingWrite() { id = null, desiredSpace = desiredSpace, k = k, ctr = null }; long id = waitingWrites.Enqueue(ww); ww.id = id; ctoken.PostRegistration(ctr => SetRegistrationForAcquireWrite(id, ctr), () => CancelAcquireWrite(id)); return(k.Task); } } } }
/// <inheritdoc /> public Task <AcquireReadResult> AcquireReadAsync(int desiredItems, CancellationToken ctoken) { if (desiredItems < 1) { return(Task.FromResult <AcquireReadResult>(new AcquireReadFaulted(new ArgumentOutOfRangeException("desiredItems", "Must be at least one")))); } if (ctoken.IsCancellationRequested) { return(Task.FromResult <AcquireReadResult>(new AcquireReadCancelled())); } else { lock (syncRoot) { if (!readLocked.HasValue && (items.Count >= desiredItems || eofSignaled)) { readLocked = Math.Min(items.Count, desiredItems); return(Task.FromResult <AcquireReadResult>(new AcquireReadSucceeded <T>(readPtr, items.GetRange(0, readLocked.Value)))); } else { TaskCompletionSource <AcquireReadResult> k = new TaskCompletionSource <AcquireReadResult>(); WaitingRead wr = new WaitingRead() { id = null, desiredItems = desiredItems, k = k, ctr = null, }; long id = waitingReads.Enqueue(wr); wr.id = id; ctoken.PostRegistration(ctr => SetRegistrationForAcquireRead(id, ctr), () => CancelAcquireRead(id)); return(k.Task); } } } }