protected long DoFiber(RCRunner runner, RCClosure closure, RCValue code) { long fiber = Interlocked.Increment(ref _fiber); RCBot bot = runner.GetBot(closure.Bot); RCClosure next = FiberClosure(bot, fiber, closure, code); bot.ChangeFiberState(fiber, "start"); RCSystem.Log.Record(closure, "fiber", fiber, "start", ""); // This creates a separate stream of execution (fiber) from the // one that called this method. // When it is done it will naturally try to return its result // back to the original calling fiber. But the Next method on the // fiber operator will see this happening and call FiberDone instead. runner.Continue(null, next); return(fiber); }
public static void DoYield(RCRunner runner, RCClosure closure, RCValue result) { if (result == null) { throw new ArgumentNullException("result"); } // Check to see if this fiber was killed before moving on RCBot bot = runner.GetBot(closure.Bot); if (bot.IsFiberDone(closure.Fiber)) { runner.Continue(closure, null); return; } // Do not permit any further changes to result or its children values. result.Lock(); RCClosure next = closure.Code.Next(runner, closure, closure, result); if (next == null) { result = closure.Code.Finish(runner, closure, result); bot.ChangeFiberState(closure.Fiber, "done"); RCSystem.Log.Record(closure, "fiber", closure.Fiber, "done", ""); if (closure.Fiber == 0 && closure.Bot == 0) { runner.Finish(closure, result); } // This will handle fibers that wake up from some suspended state // without realizing that they have been killed. else { bot.FiberDone(runner, closure.Bot, closure.Fiber, result); } // Remove closure from the pending queue. runner.Continue(closure, null); } else { runner.Continue(closure, next); } }
public void Invoke(RCRunner runner, RCClosure closure, string name, object left, object right) { OverloadValue overload; Type ltype = left.GetType(); Type rtype = right.GetType(); Type ctype = right.GetType(); try { if (_dispatch.TryGetValue(new OverloadKey(name, ctype, ltype, rtype), out overload)) { RCBot bot = runner.GetBot(closure.Bot); object state = bot.GetModule(overload.Module); overload.Implementation.Invoke(state, new object[] { runner, closure, left, right }); } else if (_dispatch.TryGetValue(new OverloadKey(name, typeof(object), ltype, rtype), out overload)) { RCBot bot = runner.GetBot(closure.Bot); object state = bot.GetModule(overload.Module); overload.Implementation.Invoke(state, new object[] { runner, closure, left, right }); } else if (_dispatch.TryGetValue(new OverloadKey(name, typeof(object), typeof(object), rtype), out overload)) { RCBot bot = runner.GetBot(closure.Bot); object state = bot.GetModule(overload.Module); overload.Implementation.Invoke(state, new object[] { runner, closure, left, right }); } else if (_dispatch.TryGetValue(new OverloadKey(name, typeof(object), ltype, typeof(object)), out overload)) { RCBot bot = runner.GetBot(closure.Bot); object state = bot.GetModule(overload.Module); overload.Implementation.Invoke(state, new object[] { runner, closure, left, right }); } else if (_dispatch.TryGetValue(new OverloadKey(name, typeof(object), typeof(object), typeof(object)), out overload)) { RCBot bot = runner.GetBot(closure.Bot); object state = bot.GetModule(overload.Module); overload.Implementation.Invoke(state, new object[] { runner, closure, left, right }); } else if (_dispatch.TryGetValue(new OverloadKey(name, typeof(object), ltype, typeof(RCOperator)), out overload)) { RCBot bot = runner.GetBot(closure.Bot); object state = bot.GetModule(overload.Module); overload.Implementation.Invoke(state, new object[] { runner, closure, left, right }); } else { throw RCException.Overload(closure, name, left, right); } } catch (TargetInvocationException tiex) { Exception ex = tiex.GetBaseException(); if (ex is RCException) { throw ex; } else { // You have to pass the tiex, not ex here so that the interior stack trace will // be // preserved when/if it is rethrown. throw new RCException(closure, tiex, RCErrors.Native, ThrowMessage(name, ex)); } } }