예제 #1
0
        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);
            }
        }
예제 #2
0
        public void Finish(RCClosure closure, Exception exception, long status)
        {
            RCValue   result = null;
            RCClosure parent = closure;
            RCBot     bot    = GetBot(closure.Bot);

            while (parent != null && parent.Bot == closure.Bot && parent.Fiber == closure.Fiber)
            {
                if (parent.InCodeEval)
                {
                    RCClosure next = parent.Code.Handle(this, parent, exception, status, out result);
                    if (result != null && next == null)
                    {
                        string state = status == 1 ? "caught" : "killed";
                        bot.ChangeFiberState(closure.Fiber, state);
                        RCSystem.Log.Record(closure, "fiber", closure.Fiber, state, exception);
                        if (closure.Fiber == 0 && closure.Bot == 0)
                        {
                            Finish(closure, result);
                        }
                        else
                        {
                            bot.FiberDone(this, closure.Bot, closure.Fiber, result);
                        }
                        return;
                    }
                    else
                    {
                        Continue(null, next);
                    }
                    if (result != null)
                    {
                        bot.ChangeFiberState(closure.Fiber, "caught");
                        RCSystem.Log.Record(closure, "fiber", closure.Fiber, "caught", exception);
                        ++_exceptionCount;
                        return;
                    }
                }
                parent = parent.Parent;
            }
            // This means it was not handled in the while loop.
            if (result == null)
            {
                string state = status == 1 ? "failed" : "killed";
                bot.ChangeFiberState(closure.Fiber, state);
                SafeLogRecord(closure, "fiber", state, exception);
                ++_exceptionCount;
                if (closure.Fiber == 0 && closure.Bot == 0)
                {
                    _exception        = exception;
                    _exceptionClosure = closure;
                    _done.Set();
                }
                else
                {
                    // I think this is sort of mostly the correct think to do.
                    // We need to record the fact that the fiber finished.
                    // But stuffing an exception inside a Native to do so seems wrong.
                    // Need more work on controlling the lifecycle of fibers.
                    // Also I want to get rid of RCNative I think this is the only place
                    // where I still need it.
                    bot.FiberDone(this, closure.Bot, closure.Fiber, new RCNative(exception));
                }
            }
        }