Beispiel #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();
        }
Beispiel #2
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 newValueA = await f(x, y, Box <A> .GetValue(value));

                var newValue = Box <A> .New(newValueA);

                if (!validator(Box <A> .GetValue(newValue)))
                {
                    return(false);
                }
                if (Interlocked.CompareExchange(ref value, newValue, current) == current)
                {
                    Change?.Invoke(newValueA);
                    return(true);
                }
                SpinWait sw = default;
                sw.SpinOnce();
            }
            throw new DeadlockException();
        }
        /// <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);