예제 #1
0
        public void FiberDone(RCRunner runner, long bot, long fiber, RCValue result)
        {
            Queue <RCClosure> waiters;
            RCValue           botResult = null;

            lock (_fiberLock)
            {
                if (_fiberWaiters.TryGetValue(fiber, out waiters))
                {
                    _fiberWaiters.Remove(fiber);
                }
                if (!_fiberResults.ContainsKey(fiber))
                {
                    _fiberResults.Add(fiber, result);
                }
                else
                {
                    // I wanted to draw a hard line and ensure this method was
                    // called only once for each fiber, by the fiber or bot operator.
                    // But it has to also be called from within try when there is nothing
                    // to do next.
                    if (!_fiberResults[fiber].Equals(result))
                    {
                        throw new Exception("Conflicting results for fiber " + fiber);
                    }
                }
                if (_fiberResults.Count == _fibers.Count)
                {
                    botResult = _fiberResults[0L];
                }
            }
            if (waiters != null)
            {
                RCNative exValue = result as RCNative;
                if (exValue != null && exValue.Value is Exception)
                {
                    foreach (RCClosure waiter in waiters)
                    {
                        runner.Finish(waiter, (Exception)exValue.Value, 1);
                    }
                }
                else
                {
                    foreach (RCClosure waiter in waiters)
                    {
                        runner.Yield(waiter, result);
                    }
                }
            }
            if (botResult != null)
            {
                runner.BotDone(bot, botResult);
            }
        }
예제 #2
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);
            }
        }
예제 #3
0
 // Kicks off evaluation for a block.
 public static void DoEval(RCRunner runner, RCClosure closure, RCBlock block)
 {
     if (block.Count == 0)
     {
         DoYield(runner, closure, block);
     }
     else
     {
         RCBlock current = block.GetName(closure.Index);
         if (current.Evaluator.Invoke)
         {
             string op = ((RCString)current.Value)[0];
             RCSystem.Activator.Invoke(runner, closure, op, closure.Result);
         }
         else if (current.Evaluator.Template)
         {
             try
             {
                 RCString result = ExpandTemplate(new StringBuilder(),
                                                  (RCTemplate)current,
                                                  closure.Result,
                                                  0,
                                                  "");
                 runner.Yield(closure, result);
             }
             catch (Exception ex)
             {
                 RCException rcex = new RCException(closure,
                                                    ex,
                                                    RCErrors.Native,
                                                    "An exception was thrown by the template.");
                 runner.Finish(closure, rcex, (int)RCErrors.Native);
             }
         }
         else if (current.Evaluator.Pass)
         {
             DoYield(runner, closure, current.Value);
         }
         // This means that Value is an operator or a reference.
         else if (current.Value.ArgumentEval)
         {
             current.Value.Eval(runner,
                                new RCClosure(closure,
                                              closure.Bot,
                                              current.Value,
                                              closure.Left,
                                              closure.Result,
                                              0));
         }
         else if (current.Evaluator.Return)
         {
             DoYield(runner, closure, current.Value);
         }
         else
         {
             // I need something different to happen when we are at the top level already.
             // Or maybe I need to inject a wrapper closure when I do Rep this way?
             if ((closure.Index < block.Count - 1) || (closure.Parent != null))
             {
                 DoYield(runner, closure, current.Value);
             }
             else
             {
                 DoYield(runner, closure, current);
             }
         }
     }
 }
예제 #4
0
 public void EvalFail(RCRunner runner, RCClosure closure, RCString right)
 {
     runner.Finish(closure,
                   new RCException(closure, RCErrors.Custom, right[0]),
                   (int)RCErrors.Custom);
 }