Пример #1
0
        // It is possible to have multiple concurrent observers.
        // However each value will only be returned to one of the observers.
        // It is hard to see a reason to create multiple observers but there
        // are multiple potential problems with implementing the constraint that there
        // be only one.
        public void Watch(RCClosure closure, long bot)
        {
            RCBlock result;

            lock (_botLock)
            {
                Queue <RCAsyncState> output = _output[bot];
                if (output.Count == 0)
                {
                    Queue <RCClosure> watchers;
                    if (!_watchers.TryGetValue(bot, out watchers))
                    {
                        watchers       = new Queue <RCClosure> ();
                        _watchers[bot] = watchers;
                    }
                    watchers.Enqueue(closure);
                    return;
                }
                RCBlock                  values = RCBlock.Empty;
                Stack <RCClosure>        parts  = new Stack <RCClosure> ();
                RCArray <RCSymbolScalar> names  = new RCArray <RCSymbolScalar> (output.Count);
                while (output.Count > 0)
                {
                    RCAsyncState   state  = output.Dequeue();
                    RCClosure      parent = state.Closure;
                    RCSymbolScalar name   = new RCSymbolScalar(null, parent.Fiber);
                    while (parent != null)
                    {
                        if (parent.Parent.Bot != parent.Bot ||
                            parent.Parent.Fiber != parent.Fiber)
                        {
                            break;
                        }
                        parts.Push(parent);
                        parent = parent.Parent;
                    }
                    while (parts.Count > 0)
                    {
                        RCClosure top = parts.Pop();
                        if (top.Code.IsBlock)
                        {
                            RCBlock code = (RCBlock)top.Code;
                            string  part = code.GetName(top.Index).Name;
                            if (part != "")
                            {
                                name = new RCSymbolScalar(name, part);
                            }
                            else
                            {
                                name = new RCSymbolScalar(name, (long)top.Index);
                            }
                        }
                    }
                    if (name != null)
                    {
                        RCValue val = (RCValue)state.Other;
                        values = new RCBlock(values, "", ":", val);
                        names.Write(name);
                    }
                }
                result = new RCBlock(null, "names", ":", new RCSymbol(names));
                result = new RCBlock(result, "values", ":", values);
            }
            Yield(closure, result);
        }
Пример #2
0
 public Wakeup(RCAsyncState state, long resetCount)
 {
     _state      = state;
     _resetCount = resetCount;
 }
Пример #3
0
 public void Wait(RCClosure closure, RCLong timeout, RCLong fibers)
 {
     // At some point I want this to work for multiple fibers,
     // but the current version will only wait on a single fiber.
     if (fibers.Count == 1)
     {
         Fiber fiber;
         lock (_botLock)
         {
             fiber = (Fiber)_bots[fibers[0]].GetModule(typeof(Fiber));
         }
         RCValue result = null;
         lock (fiber._fiberLock)
         {
             if (fiber._fiberResults.Count == fiber._fibers.Count)
             {
                 fiber._fiberResults.TryGetValue(0, out result);
             }
         }
         if (result == null)
         {
             lock (_botLock)
             {
                 Queue <RCClosure> waiters;
                 if (_botWaiters.TryGetValue(fibers[0], out waiters))
                 {
                     waiters.Enqueue(closure);
                 }
                 else
                 {
                     waiters = new Queue <RCClosure> ();
                     waiters.Enqueue(closure);
                     _botWaiters.Add(fibers[0], waiters);
                 }
                 RCAsyncState state  = new RCAsyncState(this, closure, fibers);
                 Wakeup       wakeup = new Wakeup(state, _reset);
                 Timer        timer  = new Timer(wakeup.ContinueBot);
                 timer.Change(timeout[0], Timeout.Infinite);
             }
         }
         else
         {
             SafeYieldFromWait(closure, result);
         }
     }
     else if (fibers.Count == 2)
     {
         RCValue result = null;
         Fiber   fiber;
         lock (_botLock)
         {
             fiber = (Fiber)_bots[fibers[0]].GetModule(typeof(Fiber));
         }
         lock (fiber._fiberLock)
         {
             if (!fiber._fiberResults.TryGetValue(fibers[1], out result))
             {
                 Queue <RCClosure> waiters;
                 if (fiber._fiberWaiters.TryGetValue(fibers[1], out waiters))
                 {
                     waiters.Enqueue(closure);
                 }
                 else
                 {
                     waiters = new Queue <RCClosure> ();
                     waiters.Enqueue(closure);
                     fiber._fiberWaiters.Add(fibers[1], waiters);
                 }
                 RCAsyncState state  = new RCAsyncState(this, closure, fibers);
                 Wakeup       wakeup = new Wakeup(state, _reset);
                 Timer        timer  = new Timer(wakeup.ContinueFiber);
                 timer.Change(timeout[0], Timeout.Infinite);
             }
         }
         if (result != null)
         {
             SafeYieldFromWait(closure, result);
         }
     }
     else
     {
         throw new Exception();
     }
 }