예제 #1
0
        private static Event <TA> SwitchE <TA>(Transaction trans1, Behavior <Event <TA> > bea)
        {
            var @out = new EventSink <TA>();
            var h2   = new TransactionHandler <TA>
            {
                Run = (trans2, a) => @out.Send(trans2, a)
            };
            var h1 = new TransactionHandler <Event <TA> > {
                CurrentListener = bea.SampleNoTrans().Listen(@out.Node, trans1, h2, false)
            };

            h1.Run = (trans2, ea) => trans2.Last(
                new Runnable
            {
                Run = () =>
                {
                    if (h1.CurrentListener != null)
                    {
                        h1.CurrentListener.Unlisten();
                    }
                    h1.CurrentListener = ea.Listen(@out.Node, trans2, h2, true);
                }
            });

            Listener l1 = bea.Updates().Listen(@out.Node, trans1, h1, false);

            return(@out.AddCleanup(l1));
        }
예제 #2
0
        ///
        ///Unwrap a behavior inside another behavior to give a time-varying behavior implementation.
        ///
        public static Behavior <TA> SwitchB <TA>(Behavior <Behavior <TA> > bba)
        {
            Func <TA> za   = () => bba.SampleNoTrans().SampleNoTrans();
            var       @out = new EventSink <TA>();
            var       h    = new TransactionHandler <Behavior <TA> >();

            h.Run = (trans2, ba) =>
            {
                // Note: If any switch takes place during a transaction, then the
                // value().listen will always cause a sample to be fetched from the
                // one we just switched to. The caller will be fetching our output
                // using value().listen, and value() throws away all firings except
                // for the last one. Therefore, anything from the old input behaviour
                // that might have happened during this transaction will be suppressed.
                if (h.CurrentListener != null)
                {
                    h.CurrentListener.Unlisten();
                }
                h.CurrentListener = ba.Value(trans2).Listen(
                    @out.Node,
                    trans2,
                    new TransactionHandler <TA>
                {
                    Run = (trans3, a) => @out.Send(trans3, a)
                },
                    false);
            };
            Listener l1 = bba.Value().Listen_(@out.Node, h);

            return(@out.AddCleanup(l1).HoldLazy(za));
        }
예제 #3
0
            public ListenerImplementation(Event <TA> @event, TransactionHandler <TA> action, Node target)
            {
                _event      = @event;
                this.action = action;
                this.target = target;

                Unlisten = UnlistenImpl;
            }
예제 #4
0
        ///
        ///Merge two streams of events of the same type.
        ///
        ///In the case where two event occurrences are simultaneous (i.e. both
        ///within the same transaction), both will be delivered in the same
        ///transaction. If the event firings are ordered for some reason, then
        ///their ordering is retained. In many common cases the ordering will
        ///be undefined.
        ///
        public static Event <TA> Merge <TA>(Event <TA> ea, Event <TA> eb)
        {
            var @out = new EventSink <TA>
            {
                SampleNow = () =>
                {
                    Object[] oa = ea.SampleNow();
                    Object[] ob = eb.SampleNow();
                    if (oa != null && ob != null)
                    {
                        var oo = new Object[oa.Length + ob.Length];
                        int j  = 0;
                        for (int i = 0; i < oa.Length; i++)
                        {
                            oo[j++] = oa[i];
                        }
                        for (int i = 0; i < ob.Length; i++)
                        {
                            oo[j++] = ob[i];
                        }
                        return(oo);
                    }
                    if (oa != null)
                    {
                        return(oa);
                    }
                    return(ob);
                }
            };
            var h = new TransactionHandler <TA>
            {
                Run = (trans, a) => @out.Send(trans, a)
            };
            Listener l1 = ea.Listen_(@out.Node, h);
            Listener l2 = eb.Listen_(@out.Node, new TransactionHandler <TA>
            {
                Run = (trans1, a) => trans1.Prioritized(@out.Node, new Handler <Transaction>
                {
                    Run = trans2 =>
                    {
                        @out.Send(trans2, a);
                    }
                })
            });

            return(@out.AddCleanup(l1).AddCleanup(l2));
        }
예제 #5
0
 public Listener Listen(Node target, Transaction trans, TransactionHandler <TA> action, bool suppressEarlierFirings)
 {
     lock (Transaction.ListenersLock)
     {
         if (Node.LinkTo(target))
         {
             trans.ToRegen = true;
         }
         Listeners.Add(action);
     }
     trans.Prioritized(target, new Handler <Transaction>
     {
         Run = trans2 =>
         {
             object[] aNow = SampleNow();
             if (aNow != null)
             {
                 // In cases like value(), we start with an initial value.
                 foreach (object t in aNow)
                 {
                     action.Run(trans, (TA)t); // <-- unchecked warning is here
                 }
             }
             if (!suppressEarlierFirings)
             {
                 // Anything sent already in this transaction must be sent now so that
                 // there's no order dependency between send and listen.
                 foreach (TA a in Firings)
                 {
                     action.Run(trans, a);
                 }
             }
         }
     });
     return(new ListenerImplementation <TA>(this, action, target));
 }
예제 #6
0
 public Listener Listen_(Node target, TransactionHandler <TA> action)
 {
     return(Transaction.Apply(trans1 => Listen(target, trans1, action, false)));
 }