Exemplo n.º 1
0
        public static IDisposable AutoRun(Action reaction, Action <Exception> exceptionHandler = null)
        {
            var atom = new ReactionAtom(reaction, exceptionHandler);

            atom.Get();
            return(atom);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates an reaction that should run every time anything it observes changes.
        /// It also runs once when you create the reaction itself. It only responds
        /// to changes in observable state, things you have annotated atom.
        /// </summary>
        /// <param name="reaction">A function for reaction.</param>
        /// <param name="exceptionHandler">A function that called when an exception is thrown while computing an reaction.</param>
        /// <param name="debugName">Debug name for this reaction.</param>
        /// <returns>Created reaction.</returns>
        /// <example>
        ///
        /// var counter = Atom.Value(1);
        ///
        /// var reaction = Atom.Reaction(() =>
        /// {
        ///     Debug.Log("Counter: " + counter.Value);
        /// });
        ///
        /// </example>
        public static Reaction Reaction(
            Action reaction,
            Action <Exception> exceptionHandler = null,
            string debugName = null)
        {
            var atom = new ReactionAtom(debugName, reaction, exceptionHandler);

            atom.Activate();
            return(atom);
        }
Exemplo n.º 3
0
 /// <summary>
 /// Creates an reaction that should run every time anything it observes changes.
 /// It also runs once when you create the reaction itself. It only responds
 /// to changes in observable state, things you have annotated atom.
 /// </summary>
 /// <param name="lifetime">Reaction lifetime.</param>
 /// <param name="reaction">A function for reaction.</param>
 /// <param name="exceptionHandler">A function that called when an exception is thrown while computing an reaction.</param>
 /// <param name="debugName">Debug name for this reaction.</param>
 /// <returns>Created reaction.</returns>
 /// <example>
 /// 
 /// var counter = Atom.Value(1);
 /// 
 /// Atom.Reaction(Lifetime, () =>
 /// {
 ///     Debug.Log("Counter: " + counter.Value);
 /// });
 /// 
 /// </example>
 public static Reaction Reaction(
     Lifetime lifetime,
     Action reaction,
     Action<Exception> exceptionHandler = null,
     string debugName = null)
 {
     var atom = new ReactionAtom(debugName, reaction, exceptionHandler);
     lifetime.Register(atom);
     atom.Activate();
     return atom;
 }
Exemplo n.º 4
0
        /// <summary>
        /// Creates an reaction that observes and runs the given predicate function
        /// until it returns true. Once that happens, the given effect function
        /// is executed and the reaction is deactivated.<br/>
        /// <br/>
        /// Returns a reaction, allowing you to cancel it manually.
        /// </summary>
        /// <param name="p">An observed predicate function.</param>
        /// <param name="sideEffect">An effect function.</param>
        /// <param name="exceptionHandler">A function that called when an exception is thrown while computing an reaction.</param>
        /// <param name="debugName">Debug name for this reaction.</param>
        /// <returns>Created reaction.</returns>
        /// <example>
        ///
        /// var counter = Atom.Value(1);
        ///
        /// var reaction = Atom.When(
        ///     () => counter.Value == 10,
        ///     () => Debug.Log("Counter value equals 10")
        /// );
        ///
        /// </example>
        public static Reaction When(
            Func <bool> p,
            Action sideEffect,
            Action <Exception> exceptionHandler = null,
            string debugName = null)
        {
            Reaction watcher = null;

            watcher = new ReactionAtom(debugName, () =>
            {
                Exception exception = null;
                try
                {
                    if (!p())
                    {
                        return;
                    }
                }
                catch (Exception e)
                {
                    exception = e;
                }

                if (exception != null && exceptionHandler == null)
                {
                    Debug.LogException(exception);
                    return;
                }

                using (NoWatch)
                {
                    if (exception != null)
                    {
                        exceptionHandler(exception);
                    }
                    else
                    {
                        sideEffect();
                    }

                    // ReSharper disable once AccessToModifiedClosure
                    watcher?.Deactivate();
                    watcher = null;
                }
            });

            watcher.Activate();

            return(watcher);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates an reaction that takes two functions:
        /// the first, data function, is tracked and returns the data that is used
        /// as input for the second, effect function. It is important to note that
        /// the side effect only reacts to data that was accessed in the data function,
        /// which might be less than the data that is actually used in the effect function.
        ///
        /// The typical pattern is that you produce the things you need in your side effect
        /// in the data function, and in that way control more precisely when the effect triggers.
        /// </summary>
        /// <param name="reaction">A data function.</param>
        /// <param name="effect">A side effect function.</param>
        /// <param name="exceptionHandler">A function that called when an exception is thrown while computing an reaction.</param>
        /// <param name="comparer">Data comparer used for reconciling.</param>
        /// <param name="fireImmediately">Should the side effect runs once when you create a reaction itself? Default value is true.</param>
        /// <param name="debugName">Debug name for this reaction.</param>
        /// <typeparam name="T">Reaction data type.</typeparam>
        /// <returns>Created reaction.</returns>
        /// <example>
        ///
        /// var counter = Atom.Value(1);
        ///
        /// var reaction = Atom.Reaction(
        ///     () => counter.Value,
        ///     (val, reactionHandle) =>
        ///     {
        ///         Debug.Log("Counter: " + val);
        ///         if (val == 10)
        ///         {
        ///             reactionHandle.Deactivate();
        ///         }
        ///     }
        /// );
        ///
        /// </example>
        public static Reaction Reaction <T>(
            AtomPull <T> reaction,
            Action <T, Reaction> effect,
            Action <Exception> exceptionHandler = null,
            IEqualityComparer <T> comparer      = null,
            bool fireImmediately = true,
            string debugName     = null)
        {
            var  valueAtom = Computed(reaction, comparer: comparer);
            bool firstRun  = true;

            Reaction atom = null;

            atom = new ReactionAtom(debugName, () =>
            {
                var value = valueAtom.Value;

                using (NoWatch)
                {
                    if (firstRun)
                    {
                        firstRun = false;

                        if (!fireImmediately)
                        {
                            return;
                        }
                    }

                    // ReSharper disable once AccessToModifiedClosure
                    effect(value, atom);
                }
            }, exceptionHandler);

            atom.Activate();
            return(atom);
        }
Exemplo n.º 6
0
        public static IDisposable Reaction <T>(
            AtomPull <T> pull,
            Action <T, IDisposable> reaction,
            IEqualityComparer <T> comparer      = null,
            bool fireImmediately                = false,
            Action <Exception> exceptionHandler = null)
        {
            var  valueAtom = Computed(pull, comparer: comparer);
            bool firstRun  = true;

            ReactionAtom atom = null;

            atom = new ReactionAtom(() =>
            {
                var value = valueAtom.Value;

                using (NoWatch)
                {
                    if (firstRun)
                    {
                        firstRun = false;

                        if (!fireImmediately)
                        {
                            return;
                        }
                    }

                    // ReSharper disable once AccessToModifiedClosure
                    reaction(value, atom);
                }
            }, exceptionHandler);

            atom.Get();
            return(atom);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Creates an reaction that observes and runs the given predicate function
        /// until it returns true. Once that happens, the returned task is completed
        /// and the reaction is deactivated.<br/>
        /// <br/>
        /// The task will fail if the predicate throws an exception.
        /// </summary>
        /// <param name="p">An observed predicate function.</param>
        /// <param name="cancellationToken">Token for reaction cancellation.</param>
        /// <param name="debugName">Debug name for this reaction.</param>
        /// <returns>Task that completes when the predicate returns true or predicate function throws exception.</returns>
        /// <example>
        ///
        /// var counter = Atom.Value(1);
        ///
        /// await Atom.When(() => counter.Value == 10);
        /// Debug.Log("Counter value equals 10");
        ///
        /// </example>
        public static Task When(
            Func <bool> p,
            CancellationToken cancellationToken = default,
            string debugName = null)
        {
            var taskCompletionSource = new TaskCompletionSource <object>();

            Reaction watcher = null;
            CancellationTokenRegistration?cancellationTokenRegistration = null;

            void Dispose()
            {
                taskCompletionSource.TrySetCanceled();
                // ReSharper disable once AccessToModifiedClosure
                cancellationTokenRegistration?.Dispose();
                // ReSharper disable once AccessToModifiedClosure
                watcher?.Deactivate();
                watcher = null;
            }

            watcher = new ReactionAtom(debugName, () =>
            {
                Exception exception = null;
                try
                {
                    if (!p())
                    {
                        return;
                    }
                }
                catch (Exception e)
                {
                    exception = e;
                }

                using (NoWatch)
                {
                    if (exception != null)
                    {
                        taskCompletionSource.TrySetException(exception);
                    }
                    else
                    {
                        taskCompletionSource.TrySetResult(null);
                    }

                    Dispose();
                }
            });

            if (cancellationToken.IsCancellationRequested)
            {
                Dispose();
            }
            else
            {
                watcher.Activate();

                if (cancellationToken.CanBeCanceled)
                {
                    cancellationTokenRegistration = cancellationToken.Register(Dispose, true);
                }
            }

            return(taskCompletionSource.Task);
        }