예제 #1
0
        /// <summary>
        /// Atomically updates the value by passing the old value to `f` and updating
        /// the atom with the result.  Note: `f` may be called multiple times, so it
        /// should be free of side-effects.
        /// </summary>
        /// <param name="f">Function to update the atom</param>
        /// <returns>`true` if new-value passes any validation and was successfully set.  `false`
        /// will only be returned if the `validator` fails.</returns>
        public bool Swap(Func <M, A, A> f)
        {
            f = f ?? throw new ArgumentNullException(nameof(f));

            var retries = maxRetries;

            while (retries > 0)
            {
                retries--;
                var current   = value;
                var newValueA = f(metadata, Box <A> .GetValue(value));
                var newValue  = Box <A> .New(newValueA);

                if (!validator(newValueA))
                {
                    return(false);
                }
                if (Interlocked.CompareExchange(ref value, newValue, current) == current)
                {
                    Change?.Invoke(newValueA);
                    return(true);
                }
                SpinWait sw = default;
                sw.SpinOnce();
            }
            throw new DeadlockException();
        }
예제 #2
0
        Atom(M metadata, A value, Func <A, bool> validator)
        {
            this.value = Box <A> .New(value);

            this.metadata  = metadata;
            this.validator = validator;
        }
예제 #3
0
        /// <summary>
        /// Atomically updates the value by passing the old value to `f` and updating
        /// the atom with the result.  Note: `f` may be called multiple times, so it
        /// should be free of side-effects.
        /// </summary>
        /// <param name="x">Additional value to pass to `f`</param>
        /// <param name="y">Additional value to pass to `f`</param>
        /// <param name="f">Function to update the atom</param>
        /// <returns>`true` if new-value passes any validation and was successfully set.  `false`
        /// will only be returned if the `validator` fails.</returns>
        public async Task <bool> SwapAsync <X, Y>(X x, Y y, Func <X, Y, A, Task <A> > f)
        {
            f = f ?? throw new ArgumentNullException(nameof(f));

            var retries = maxRetries;

            while (retries > 0)
            {
                retries--;
                var current  = value;
                var newValue = Box.New(await f(x, y, value.Value));
                if (!validator(newValue.Value))
                {
                    return(false);
                }
                if (Interlocked.CompareExchange(ref value, newValue, current) == current)
                {
                    Change?.Invoke(newValue.Value);
                    return(true);
                }
                SpinWait sw = default;
                sw.SpinOnce();
            }
            throw new DeadlockException();
        }
예제 #4
0
        /// <summary>
        /// Atomically updates the value by passing the old value to `f` and updating
        /// the atom with the result.  Note: `f` may be called multiple times, so it
        /// should be free of side-effects.
        /// </summary>
        /// <param name="f">Function to update the atom</param>
        /// <returns>Option in a Some state, with the result of the invocation of `f`, if the swap succeeded
        /// and its validation passed. None otherwise</returns>
        public Option <A> Swap(Func <M, A, A> f)
        {
            f = f ?? throw new ArgumentNullException(nameof(f));

            SpinWait sw = default;

            while (true)
            {
                var current   = value;
                var newValueA = f(metadata, Box <A> .GetValue(value));
                var newValue  = Box <A> .New(newValueA);

                if (!validator(newValueA))
                {
                    return(default);
예제 #5
0
 Atom(A value, Func <A, bool> validator)
 {
     this.value     = Box.New(value);
     this.validator = validator;
 }