private void OnFiberInstruction(Fiber fiber, FiberInstruction instruction, out bool fiberQueued, out Fiber nextFiber) { fiberQueued = false; nextFiber = null; YieldUntilComplete yieldUntilComplete = instruction as YieldUntilComplete; if (yieldUntilComplete != null) { // The additional complexity below is because this was going // to handle waiting for completions for fibers from other threads. // Currently fibers must belong to the same thread and this is enforced // by the instructions themselves for now. int completeOnce = 0; // FIXME: If we support multiple schedulers in the future // this callback could occur from another thread and // therefore after Dispose(). Would probably need a lock. // Watch for completion EventHandler <EventArgs> completed; completed = (sender, e) => { var originalCompleteOnce = Interlocked.CompareExchange(ref completeOnce, 1, 0); if (originalCompleteOnce != 0) { return; } yieldUntilComplete.Fiber.Completed -= completed; //QueueFiberForExecution(fiber); QueueFiber(fiber); // optionally execute inline when the completion occurs }; yieldUntilComplete.Fiber.Completed += completed; // If the watched fiber is already complete then continue immediately if (yieldUntilComplete.Fiber.FiberState == FiberState.Stopped) { completed(yieldUntilComplete.Fiber, EventArgs.Empty); } fiberQueued = true; return; } YieldForSeconds yieldForSeconds = instruction as YieldForSeconds; if (yieldForSeconds != null) { QueueFiberForSleep(fiber, currentTime + yieldForSeconds.Seconds); fiberQueued = true; return; } YieldToFiber yieldToFiber = instruction as YieldToFiber; if (yieldToFiber != null) { RemoveFiberFromQueues(yieldToFiber.Fiber); nextFiber = yieldToFiber.Fiber; fiberQueued = false; return; } }
private void OnFiberInstruction(Fiber fiber, FiberInstruction instruction, out bool fiberQueued, out Fiber nextFiber) { fiberQueued = false; nextFiber = null; YieldUntilComplete yieldUntilComplete = instruction as YieldUntilComplete; if (yieldUntilComplete != null) { // The additional complexity below is because this was going // to handle waiting for completions for fibers from other threads. // Currently fibers must belong to the same thread and this is enforced // by the instructions themselves for now. int completeOnce = 0; // FIXME: If we support multiple schedulers in the future // this callback could occur from another thread and // therefore after Dispose(). Would probably need a lock. yieldUntilComplete.Fiber.ContinueWith((f) => { var originalCompleteOnce = Interlocked.CompareExchange(ref completeOnce, 1, 0); if (originalCompleteOnce != 0) { return; } QueueFiber(fiber); // optionally execute inline when the completion occurs // If f.Status != RanToCompletion then this fiber needs to transition to the same state // or faults won't propegate //if (f.Status != FiberStatus.RanToCompletion) { // if (f.IsCanceled) { // if (f.CancellationToken == fiber.CancellationToken) { // fiber.CancelContinuation (); // } else { // fiber.FaultContinuation (new System.Threading.OperationCanceledException ()); // } // } else if (f.IsFaulted) { // fiber.FaultContinuation (f.Exception); // } // RemoveFiberFromQueues (fiber); //} else { // QueueFiber (fiber); // optionally execute inline when the completion occurs //} }); fiberQueued = true; return; } YieldForSeconds yieldForSeconds = instruction as YieldForSeconds; if (yieldForSeconds != null) { QueueFiberForSleep(fiber, currentTime + yieldForSeconds.Seconds); fiberQueued = true; return; } YieldToFiber yieldToFiber = instruction as YieldToFiber; if (yieldToFiber != null) { RemoveFiberFromQueues(yieldToFiber.Fiber); nextFiber = yieldToFiber.Fiber; fiberQueued = false; return; } }