private void AddTask(Task awaitedTask) { Contract.Requires(Thread.VolatileRead(ref _ready) == 0); if (awaitedTask.Status != TaskStatus.RanToCompletion) { Interlocked.Increment(ref _count); if (awaitedTask.AddTaskContinuation(this, /*addBeforeOthers:*/ true)) { var tasks = Interlocked.CompareExchange(ref _tasks, null, null); if (tasks == null) { return; } var index = Array.IndexOf(tasks, null); while (Interlocked.CompareExchange(ref tasks[index], awaitedTask, null) != null) { index = (index + 1) % tasks.Length; } } else { Interlocked.Decrement(ref _count); } } }
private void AddTask(Task awaitedTask) { Contract.Requires(Thread.VolatileRead(ref _ready) == 0); Interlocked.Increment(ref _count); if (!awaitedTask.AddTaskContinuation(this, /*addBeforeOthers:*/ true)) { Interlocked.Decrement(ref _count); } }
private void AddTask(Task awaitedTask) { Contract.Requires(Thread.VolatileRead(ref _ready) == 0); // Get the tasks var tasks = Interlocked.CompareExchange(ref _tasks, null, null); // If there are no tasks (Disposed) there is nothing to do if (tasks == null) { return; } // Only add tasks taht has not completed if (awaitedTask.Status == TaskStatus.RanToCompletion) { return; } // Preemptively increment _count // So that is has already been incremented when the continuation runs Interlocked.Increment(ref _count); // Add the continuation if (awaitedTask.AddTaskContinuation(this, /*addBeforeOthers:*/ true)) { // Find a spot in the tasks var index = Array.IndexOf(tasks, null); // Try to add the task while (Interlocked.CompareExchange(ref tasks[index], awaitedTask, null) != null) { index = (index + 1) % tasks.Length; } // Check again if the task has completed, it may have completed while we were adding it if (awaitedTask.Status == TaskStatus.RanToCompletion) { // Perhaps it did complete: // - Before adding the continuation -> nothing to do // - After adding the continuation before adding the task -> We have an orphan task to remove // - After adding the continuation and the task -> nothing to do // Remove the orphan task if it is there Interlocked.CompareExchange(ref tasks[index], null, awaitedTask); // Note: we let the continuation decrement _count } } else { // We failed to add the continuation // Decrement the _count Interlocked.Decrement(ref _count); CheckCount(); } }