Пример #1
0
        public static void SimpleSync()
        {
            var control = new int[3];
            var thread  = new Thread
                          (
                () =>
            {
                var spinWait = new SpinWait();
                Volatile.Write(ref control[0], 1);
                while (Volatile.Read(ref control[1]) == 0)
                {
                    spinWait.SpinOnce();
                }

                Volatile.Write(ref control[2], 1);
            }

                          );

            thread.Start();
            ThreadingHelper.SpinWaitUntil(ref control[0], 1);
            Volatile.Write(ref control[1], 1);
            thread.Join();
            Assert.AreEqual(1, Volatile.Read(ref control[2]));
        }
Пример #2
0
        private ManualResetEvent RetriveWaitHandle()
        {
            // At the end of this method: _requested will be 2 or ObjectDisposedException is thrown
            var found = Interlocked.CompareExchange(ref _requested, 1, 0);

            switch (found)
            {
            case -1:
                throw new ObjectDisposedException(GetType().FullName);

            case 0:
                // Found 0, was set to 1, create the wait handle
                var isSet = Thread.VolatileRead(ref _state) != 0;
                // State may have been set here
                var created = new ManualResetEvent(isSet);
                if (Interlocked.CompareExchange(ref _handle, created, null) != null)
                {
                    created.Close();
                }
                Thread.VolatileWrite(ref _requested, 2);
                goto default;

            case 1:
                // Found 1, another thread is creating the wait handle
                ThreadingHelper.SpinWaitUntil(ref _requested, 2);
                goto default;

            default:
                // Found 2, the wait handle is already created
                // Check if dispose has been called
                return(TryGetWaitHandleExtracted());
            }
        }
Пример #3
0
        private void CaptureAndWait(LockableSlot slot)
        {
            Capture(slot);
            var thread = Thread.CurrentThread;

            // The reason while I cannot make an smarter wait function:
            // If another thread changed _needleLock.Value after the check but before the starting to wait, the wait will not finish.
            ThreadingHelper.SpinWaitUntil(() => _needleLock.Value == thread);
        }
Пример #4
0
        internal LockableSlot(LockableContext context)
        {
            _context      = context;
            _parent       = _context.Slot;
            _context.Slot = this;
            // --
            LockSlot <Thread> lockSlot = null;

            ThreadingHelper.SpinWaitUntil(() => _context.Context.ClaimSlot(out lockSlot));
            lockSlot.Value = Thread.CurrentThread;
            _lockSlot      = lockSlot;
            _needleLocks   = new List <NeedleLock <Thread> >();
        }
Пример #5
0
 public ReadOnlyPromise(IPromise promised, bool allowWait)
 {
     _promised = promised;
     if (allowWait)
     {
         if (_promised is IWaitablePromise promise)
         {
             _wait = promise.Wait;
         }
         else
         {
             _wait = () => ThreadingHelper.SpinWaitUntil(() => _promised.IsCompleted);
         }
     }
     else
     {
         _wait =
             () => throw new InvalidOperationException();
     }
 }
Пример #6
0
        private ManualResetEvent GetWaitHandle()
        {
            var found = Thread.VolatileRead(ref _requested);

            switch (found)
            {
            case -1:
                throw new ObjectDisposedException(GetType().FullName);

            case 0:
                return(null);

            case 1:
                // Found 1, another thread is creating the wait handle
                ThreadingHelper.SpinWaitUntil(ref _requested, 2);
                goto default;

            default:
                // Found 2, the wait handle is already created
                // Check if dispose has been called
                return(TryGetWaitHandleExtracted());
            }
        }
Пример #7
0
 public ReadOnlyPromise(IPromise promised, bool allowWait)
 {
     _promised = promised;
     if (allowWait)
     {
         var promise = _promised as IWaitablePromise;
         if (promise != null)
         {
             _wait = () => promise.Wait();
         }
         else
         {
             _wait = () => ThreadingHelper.SpinWaitUntil(() => _promised.IsCompleted);
         }
     }
     else
     {
         _wait = () =>
         {
             throw new InvalidOperationException();
         };
     }
 }
Пример #8
0
        public bool Commit()
        {
            if (_currentTransaction != this)
            {
                throw new InvalidOperationException("Cannot commit a non-current transaction.");
            }

            ThreadingHelper.MemoryBarrier();
            try
            {
                if (!CheckValue())
                {
                    //the resources has been modified by another thread
                    return(false);
                }
                try
                {
                    ThreadingHelper.SpinWaitUntil(() => Context.ClaimSlot(out LockSlot));
                    LockSlot.Value = Thread.CurrentThread;
                    if (!Capture())
                    {
                        //Nothing to commit
                        return(true);
                    }
                    ThreadingHelper.MemoryBarrier();
                    if (!CheckCapture() || !CheckValue())
                    {
                        //the resources has been claimed by another thread
                        return(false);
                    }
                    var written = false;
                    foreach (var resource in WriteLog)
                    {
                        if (resource.Key.Commit())
                        {
                            written = true;
                        }
                        else
                        {
                            //unexpected
                            if (written)
                            {
                                // TODO - the transaction was partially written, this should not be possible.
                                System.Diagnostics.Debug.Fail("unexpected - partially committed transaction");
                            }
                            return(false);
                        }
                    }
                    return(true);
                }
                finally
                {
                    if (LockSlot != null)
                    {
                        LockSlot.Close();
                        LockSlot = null;
                    }
                }
            }
            finally
            {
                Release(false);
            }
        }
Пример #9
0
        public Progressor(IEnumerable <T> preface, Progressor <T> wrapped)
        {
            if (wrapped == null)
            {
                throw new ArgumentNullException("wrapped");
            }
            if (preface == null)
            {
                throw new ArgumentNullException("preface");
            }
            var enumerator = preface.GetEnumerator();

            if (enumerator == null)
            {
                throw new ArgumentException("preface.GetEnumerator()");
            }

            var control = 0;
            var guard   = 0;

            Predicate <T> newFilter = item => Thread.VolatileRead(ref control) == 0;
            var           buffer    = new SafeQueue <T>();

            wrapped.SubscribeAction
            (
                item =>
            {
                if (newFilter(item))
                {
                    buffer.Add(item);
                }
            }
            );
            _proxy = new ProxyObservable <T>();

            TryTake <T> tryTakeReplacement = (out T value) =>
            {
                Interlocked.Increment(ref control);
                try
                {
                    if (buffer.TryTake(out value) || wrapped.TryTake(out value))
                    {
                        _proxy.OnNext(value);
                        return(true);
                    }
                    else
                    {
                        _done = wrapped._done;
                        return(false);
                    }
                }
                finally
                {
                    Interlocked.Decrement(ref control);
                }
            };

            _tryTake = (out T value) =>
            {
                value = default(T);
                if (Thread.VolatileRead(ref guard) == 0)
                {
                    bool result;
                    // We need a lock, there is no way around it. IEnumerator is just awful. Use another overload if possible.
                    lock (enumerator)
                    {
                        result = enumerator.MoveNext();
                        if (result)
                        {
                            value = enumerator.Current;
                        }
                    }
                    if (result)
                    {
                        _proxy.OnNext(value);
                        return(true);
                    }
                    enumerator.Dispose();
                    Interlocked.CompareExchange(ref guard, 1, 0);
                }
                if (Interlocked.CompareExchange(ref guard, 2, 1) == 1)
                {
                    _tryTake = tryTakeReplacement;
                    Thread.VolatileWrite(ref guard, 3);
                }
                else
                {
                    ThreadingHelper.SpinWaitUntil(ref guard, 3);
                }
                var tryTake = _tryTake;
                return(tryTake(out value));
            };
        }
Пример #10
0
        public Progressor(T[] preface, Progressor <T> wrapped)
        {
            if (wrapped == null)
            {
                throw new ArgumentNullException("wrapped");
            }
            if (preface == null)
            {
                throw new ArgumentNullException("preface");
            }

            var control = 0;
            var guard   = 0;
            var index   = -1;

            Predicate <T> newFilter = item => Thread.VolatileRead(ref control) == 0;
            var           buffer    = new SafeQueue <T>();

            wrapped.SubscribeAction
            (
                item =>
            {
                if (newFilter(item))
                {
                    buffer.Add(item);
                }
            }
            );
            _proxy = new ProxyObservable <T>();

            TryTake <T> tryTakeReplacement = (out T value) =>
            {
                Interlocked.Increment(ref control);
                try
                {
                    if (buffer.TryTake(out value) || wrapped.TryTake(out value))
                    {
                        _proxy.OnNext(value);
                        return(true);
                    }
                    else
                    {
                        _done = wrapped._done;
                        return(false);
                    }
                }
                finally
                {
                    Interlocked.Decrement(ref control);
                }
            };

            _tryTake = (out T value) =>
            {
                if (Thread.VolatileRead(ref guard) == 0)
                {
                    var currentIndex = Interlocked.Increment(ref index);
                    if (currentIndex < preface.Length)
                    {
                        value = preface[currentIndex];
                        _proxy.OnNext(value);
                        return(true);
                    }
                    Interlocked.CompareExchange(ref guard, 1, 0);
                }
                if (Interlocked.CompareExchange(ref guard, 2, 1) == 1)
                {
                    _tryTake = tryTakeReplacement;
                    Thread.VolatileWrite(ref guard, 3);
                }
                else
                {
                    ThreadingHelper.SpinWaitUntil(ref guard, 3);
                }
                var tryTake = _tryTake;
                return(tryTake(out value));
            };
        }
Пример #11
0
 public static bool SpinUntil(Func <bool> condition, int millisecondsTimeout)
 {
     return(ThreadingHelper.SpinWaitUntil(condition, TimeSpan.FromMilliseconds(millisecondsTimeout)));
 }
Пример #12
0
 public static void SpinUntil(Func <bool> condition)
 {
     ThreadingHelper.SpinWaitUntil(condition);
 }