예제 #1
0
        /// <summary>
        ///     Unwrap a stream inside a cell to give a time-varying stream implementation.
        ///     When the cell changes value, the output stream will fire the simultaneous firing (if one exists) from the stream which the cell will hold at the end of the transaction.
        /// </summary>
        /// <typeparam name="T">The type of the stream.</typeparam>
        /// <param name="csa">The cell containing the stream.</param>
        /// <returns>The unwrapped stream.</returns>
        public static Stream <T> SwitchEarlyS <T>(this Cell <Stream <T> > csa)
        {
            return(Transaction.Apply(trans1 =>
            {
                Stream <T> @out = new Stream <T>(csa.KeepListenersAlive);
                Node <T> node = new Node <T>();
                (bool changed, Node <T> .Target nodeTarget) = node.Link(trans1, (t, v) => { }, @out.Node);
                if (changed)
                {
                    trans1.SetNeedsRegenerating();
                }
                Guid listenerId;

                void SendIfNodeTargetMatches(Transaction t, (T Value, Guid ListenerId)v, Guid i)
                {
                    if (v.ListenerId == i)
                    {
                        @out.Send(t, v.Value);
                    }
                }

                MutableListener currentListener = new MutableListener();

                void Handler(Transaction trans2, Stream <T> sa)
                {
                    currentListener.Unlisten();

                    listenerId = Guid.NewGuid();
                    currentListener.SetListener(sa.Map(v => (Value: v, ListenerId: listenerId)).Listen(@out.Node, trans2, (t, v) => SendIfNodeTargetMatches(t, v, listenerId), false));
                }

                IListener l1 = csa.Value(trans1).Listen(node, trans1, Handler, false);
                return @out.UnsafeAttachListener(l1).UnsafeAttachListener(currentListener).UnsafeAttachListener(Listener.Create(node, nodeTarget));
            }, false));
        }
예제 #2
0
        /// <summary>
        ///     Unwrap a stream inside a cell to give a time-varying stream implementation.
        ///     When the cell changes value, the output stream will fire the simultaneous firing (if one exists) from the stream which the cell will hold at the end of the transaction.
        /// </summary>
        /// <typeparam name="T">The type of the stream.</typeparam>
        /// <param name="csa">The cell containing the stream.</param>
        /// <returns>The unwrapped stream.</returns>
        public static Stream <T> SwitchEarlyS <T>(this Cell <Stream <T> > csa)
        {
            return(Transaction.Apply(trans1 =>
            {
                Stream <T> @out = new Stream <T>();
                Node <T> node = new Node <T>();
                Node <T> .Target nodeTarget = node.Link(trans1, (t, v) => { }, @out.Node).Item2;
                Guid listenerId;
                Action <Transaction, Tuple <T, Guid>, Guid> sendIfNodeTargetMatches = (t, v, i) =>
                {
                    if (v.Item2 == i)
                    {
                        @out.Send(t, v.Item1);
                    }
                };
                IListener currentListener = null;
                Action <Transaction, Stream <T> > h = (trans2, sa) =>
                {
                    currentListener?.Unlisten();

                    listenerId = Guid.NewGuid();
                    currentListener = sa.Map(v => Tuple.Create(v, listenerId)).Listen(@out.Node, trans2, (t, v) => sendIfNodeTargetMatches(t, v, listenerId), false);
                };
                IListener l1 = csa.Value(trans1).Listen(node, trans1, h, false);
                return @out.UnsafeAttachListener(l1).UnsafeAttachListener(Listener.Create(node, nodeTarget));
            }, false));
        }
예제 #3
0
        /// <summary>
        ///     Unwrap a stream inside a cell to give a time-varying stream implementation.
        ///     When the cell changes value, the output stream will fire the simultaneous firing (if one exists) from the stream which the cell will hold at the end of the transaction.
        /// </summary>
        /// <typeparam name="T">The type of the stream.</typeparam>
        /// <param name="csa">The cell containing the stream.</param>
        /// <returns>The unwrapped stream.</returns>
        public static Stream <T> SwitchEarlyS <T>(this Cell <Stream <T> > csa)
        {
            return(Transaction.Apply(trans1 =>
            {
                Stream <T> @out = new Stream <T>(csa.KeepListenersAlive);
                Node <T> node = new Node <T>();
                ValueTuple <bool, Node <T> .Target> r = node.Link(trans1, (t, v) => { }, @out.Node);
                Node <T> .Target nodeTarget = r.Item2;
                if (r.Item1)
                {
                    trans1.SetNeedsRegenerating();
                }
                Guid listenerId;
                Action <Transaction, ValueTuple <T, Guid>, Guid> sendIfNodeTargetMatches = (t, v, i) =>
                {
                    if (v.Item2 == i)
                    {
                        @out.Send(t, v.Item1);
                    }
                };
                MutableListener currentListener = new MutableListener();
                Action <Transaction, Stream <T> > h = (trans2, sa) =>
                {
                    currentListener.Unlisten();

                    listenerId = Guid.NewGuid();
                    currentListener.SetListener(sa.Map(v => ValueTuple.Create(v, listenerId)).Listen(@out.Node, trans2, (t, v) => sendIfNodeTargetMatches(t, v, listenerId), false));
                };
                IListener l1 = csa.Value(trans1).Listen(node, trans1, h, false);
                return @out.UnsafeAttachListener(l1).UnsafeAttachListener(currentListener).UnsafeAttachListener(Listener.Create(node, nodeTarget));
            }, false));
        }
예제 #4
0
        /// <summary>
        ///     Unwrap a cell inside another cell to give a time-varying cell implementation.
        /// </summary>
        /// <typeparam name="T">The type of the cell.</typeparam>
        /// <param name="cca">The cell containing another cell.</param>
        /// <returns>The unwrapped cell.</returns>
        public static Cell <T> SwitchC <T>(this Cell <Cell <T> > cca)
        {
            return(Transaction.Apply(trans1 =>
            {
                Lazy <T> za = cca.SampleLazy().Map(ca => ca.Sample());
                Stream <T> @out = new Stream <T>(cca.KeepListenersAlive);
                MutableListener currentListener = new MutableListener();
                Action <Transaction, Cell <T> > h = (trans2, ca) =>
                {
                    currentListener.Unlisten();

                    currentListener.SetListener(ca.Value(trans2).Listen(@out.Node, trans2, @out.Send, false));
                };
                IListener l1 = cca.Value(trans1).Listen(@out.Node, trans1, h, false);
                return @out.UnsafeAttachListener(l1).UnsafeAttachListener(currentListener).HoldLazyInternal(za);
            }, false));
        }
예제 #5
0
        /// <summary>
        ///     Unwrap a cell inside another cell to give a time-varying cell implementation.
        /// </summary>
        /// <typeparam name="T">The type of the cell.</typeparam>
        /// <param name="cca">The cell containing another cell.</param>
        /// <returns>The unwrapped cell.</returns>
        public static Cell <T> SwitchC <T>(this Cell <Cell <T> > cca)
        {
            return(Transaction.Apply(trans1 =>
            {
                Lazy <T> za = cca.SampleLazy().Map(ca => ca.Sample());
                Stream <T> @out = new Stream <T>();
                IListener currentListener = null;
                Action <Transaction, Cell <T> > h = (trans2, ca) =>
                {
                    using (currentListener)
                    {
                    }

                    currentListener = ca.Value(trans2).Listen(@out.Node, trans2, (trans3, a) => @out.Send(trans3, a), false);
                };
                IListener l1 = cca.Value(trans1).Listen(@out.Node, trans1, h, false);
                return @out.UnsafeAddCleanup(l1).HoldLazy(za);
            }));
        }