예제 #1
0
        private void Start(long dueTime)
        {
            if (dueTime < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(dueTime));
            }

            if (Interlocked.CompareExchange(ref _status, _started, _created) == _created)
            {
                _startTime  = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow());
                _targetTime = dueTime == -1 ? -1 : _startTime + dueTime;
                _wrapped    = Timer.GetTimer(Finish, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(-1));
            }
        }
예제 #2
0
        private static void Initialize()
        {
            switch (Interlocked.CompareExchange(ref _status, _statusPending, _statusNotReady))
            {
            case _statusNotReady:
                GC.KeepAlive(new GCProbe());
                Volatile.Write(ref _status, _statusReady);
                break;

            case _statusPending:
                ThreadingHelper.SpinWaitUntil(ref _status, _statusReady);
                break;
            }
        }
예제 #3
0
        public static void TimeoutFinishAndChange()
        {
            var value   = new[] { 0 };
            var timeout = RootedTimeout.Launch(() => value[0] = 1, 100);

            Assert.IsFalse(timeout.IsCanceled);
            ThreadingHelper.SpinWaitUntil(() => timeout.IsCompleted);
            Assert.IsFalse(timeout.IsCanceled);
            Assert.IsTrue(timeout.IsCompleted);
            Assert.AreEqual(1, value[0]);
            Assert.IsFalse(timeout.Change(1000));
            Assert.IsFalse(timeout.IsCanceled);
            Assert.IsTrue(timeout.IsCompleted);
        }
예제 #4
0
 private void Finish()
 {
     ThreadingHelper.SpinWaitWhile(ref _status, _changing);
     if (Interlocked.CompareExchange(ref _status, _executing, _created) == _created)
     {
         var callback = Volatile.Read(ref Callback);
         if (callback != null)
         {
             callback.Invoke();
             Close();
             Volatile.Write(ref _status, _executed);
         }
     }
 }
예제 #5
0
        public long CheckRemaining()
        {
            if (_targetTime == -1)
            {
                return(-1);
            }
            var remaining = _targetTime - ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow());

            if (remaining <= 0)
            {
                Finish(null);
                return(0);
            }
            return(remaining);
        }
예제 #6
0
        private void WaitCanWrite()
        {
            if (Thread.CurrentThread != ThreadingHelper.VolatileRead(ref _ownerThread))
            {
                var check = Interlocked.CompareExchange(ref _master, -1, 0);
                while (true)
                {
                    switch (check)
                    {
                    case -2:
                    // Write mode already requested
                    case -1:
                        // There is another writer
                        // Go to wait
                        _freeToWrite.Wait();
                        check = Interlocked.CompareExchange(ref _master, -1, 0);
                        break;

                    case 0:
                        // Free to proceed
                        // GO!
                        _freeToRead.Reset();
                        if (Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null) == null)
                        {
                            // Success
                            Interlocked.Increment(ref _writeCount);
                            return;
                        }
                        else
                        {
                            // It was reserved by another thread
                            break;
                        }

                    case 1:
                        // There are readers currently
                        // Requesting write mode
                        check = Interlocked.CompareExchange(ref _master, -2, 1);
                        if (check == 1)
                        {
                            _freeToRead.Reset();
                            check = -2;
                        }
                        break;
                    }
                }
            }
        }
예제 #7
0
        private static void Initialize()
        {
            var check = Interlocked.CompareExchange(ref _status, INT_StatusPending, INT_StatusNotReady);

            switch (check)
            {
            case INT_StatusNotReady:
                GC.KeepAlive(new GCProbe());
                Thread.VolatileWrite(ref _status, INT_StatusReady);
                break;

            case INT_StatusPending:
                ThreadingHelper.SpinWaitUntil(ref _status, INT_StatusReady);
                break;
            }
        }
예제 #8
0
        public static void TimeoutChange()
        {
again:
            var now = DateTime.Now;
            var value   = new[] { now };
            var timeout = RootedTimeout.Launch(() => value[0] = DateTime.Now, 100);

            if (!timeout.Change(1000))
            {
                goto again;
            }
            Assert.IsFalse(timeout.IsCanceled);
            Assert.IsFalse(timeout.IsCompleted);
            ThreadingHelper.SpinWaitUntil(() => timeout.IsCompleted);
            Assert.Greater((value[0] - now).TotalMilliseconds, 100);
        }
예제 #9
0
 public TReturn DisposedConditional <TReturn>(Func <TReturn> whenDisposed, Func <TReturn> whenNotDisposed)
 {
     if (_status == -1)
     {
         if (ReferenceEquals(whenDisposed, null))
         {
             return(default(TReturn));
         }
         else
         {
             return(whenDisposed.Invoke());
         }
     }
     else
     {
         if (ReferenceEquals(whenNotDisposed, null))
         {
             return(default(TReturn));
         }
         else
         {
             if (ThreadingHelper.SpinWaitRelativeSet(ref _status, 1, -1))
             {
                 try
                 {
                     return(whenNotDisposed.Invoke());
                 }
                 finally
                 {
                     System.Threading.Interlocked.Decrement(ref _status);
                 }
             }
             else
             {
                 if (ReferenceEquals(whenDisposed, null))
                 {
                     return(default(TReturn));
                 }
                 else
                 {
                     return(whenDisposed.Invoke());
                 }
             }
         }
     }
 }
예제 #10
0
 private bool CanRead()
 {
     if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread))
     {
         Interlocked.Increment(ref _readCount);
         _currentReadingCount.Value++;
         return(true);
     }
     if (Interlocked.CompareExchange(ref _master, 1, 0) >= 0)
     {
         _freeToWrite.Reset();
         Interlocked.Increment(ref _readCount);
         _currentReadingCount.Value++;
         return(true);
     }
     return(false);
 }
예제 #11
0
        /// <summary>
        /// Adds the specified item at the front.
        /// </summary>
        /// <param name="item">The item.</param>
        public void Enqueue(T item)
        {
            bool result = false;

            while (true)
            {
                if (IsOperationSafe())
                {
                    var  entries = ThreadingHelper.VolatileRead(ref _entriesNew);
                    bool done    = false;
                    try
                    {
                        Interlocked.Increment(ref _workingThreads);
                        if (entries.Enqueue(item))
                        {
                            result = true;
                        }
                    }
                    finally
                    {
                        Interlocked.Decrement(ref _workingThreads);
                        if (result)
                        {
                            Interlocked.Increment(ref _count);
                            done = true;
                        }
                        else
                        {
                            var oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.GrowRequested, (int)BucketStatus.Free);
                            if (oldStatus == (int)BucketStatus.Free)
                            {
                                _revision++;
                            }
                        }
                    }
                    if (done)
                    {
                        return;
                    }
                }
                else
                {
                    CooperativeGrow();
                }
            }
        }
예제 #12
0
 public bool Change(long dueTime)
 {
     if (Interlocked.CompareExchange(ref _status, _changing, _created) == _created)
     {
         _startTime  = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow());
         _targetTime = _startTime + dueTime;
         var wrapped = Interlocked.CompareExchange(ref _wrapped, null, null);
         if (wrapped == null)
         {
             return(false);
         }
         wrapped.Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(-1));
         Volatile.Write(ref _status, _created);
         return(true);
     }
     return(false);
 }
예제 #13
0
 protected void Start(long dueTime)
 {
     if (dueTime < -1)
     {
         throw new ArgumentOutOfRangeException("dueTime");
     }
     _startTime = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow());
     if (dueTime == -1)
     {
         _targetTime = -1;
     }
     else
     {
         _targetTime = _startTime + dueTime;
     }
     _wrapped = new Timer(Finish, null, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(-1));
 }
예제 #14
0
        public static void TimeoutChange()
        {
            RootedTimeout timeout;
            var           value = new DateTime[1];
            DateTime      now;

            do
            {
                now      = DateTime.Now;
                value[0] = now;
                timeout  = RootedTimeout.Launch(() => value[0] = DateTime.Now, 100);
            }while (!timeout.Change(1000));

            Assert.IsFalse(timeout.IsCanceled);
            Assert.IsFalse(timeout.IsCompleted);
            ThreadingHelper.SpinWaitUntil(() => timeout.IsCompleted);
            Assert.Greater((value[0] - now).TotalMilliseconds, 100);
        }
예제 #15
0
 private void Initialize(long dueTime)
 {
     if (Thread.VolatileRead(ref _executed) == 1)
     {
         ThreadingHelper.SpinWaitWhile(ref _completed, 1);
         Thread.VolatileWrite(ref _executed, 0);
     }
     _start      = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow());
     _targetTime = _start + dueTime;
     if (_wrapped == null)
     {
         _wrapped = new Timer(Callback, null, dueTime, System.Threading.Timeout.Infinite);
     }
     else
     {
         _wrapped.Change(dueTime, System.Threading.Timeout.Infinite);
     }
 }
예제 #16
0
        /// <summary>
        /// Tries to retrieve the key and associated value at the specified index.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        ///   <c>true</c> if the value was retrieved; otherwise, <c>false</c>.
        /// </returns>
        public bool TryGet(int index, out TKey key, out TValue value)
        {
            value = default(TValue);
            key   = default(TKey);
            bool result = false;
            int  revision;

            while (true)
            {
                revision = _revision;
                if (IsOperationSafe())
                {
                    var  entries = ThreadingHelper.VolatileRead(ref _entriesNew);
                    bool done    = false;
                    try
                    {
                        TValue tmpValue;
                        TKey   tmpKey;
                        if (TryGetExtracted(index, entries, out tmpKey, out tmpValue))
                        {
                            key    = tmpKey;
                            value  = tmpValue;
                            result = true;
                        }
                    }
                    finally
                    {
                        var isOperationSafe = IsOperationSafe(entries, revision);
                        if (isOperationSafe)
                        {
                            done = true;
                        }
                    }
                    if (done)
                    {
                        return(result);
                    }
                }
                else
                {
                    CooperativeGrow();
                }
            }
        }
예제 #17
0
        private void Finish()
        {
            ThreadingHelper.SpinWaitWhile(ref _status, _changing);
            if (Interlocked.CompareExchange(ref _status, _executing, _started) != _started)
            {
                return;
            }

            var callback = Volatile.Read(ref _callback);

            if (callback == null)
            {
                return;
            }

            callback.Invoke();
            Volatile.Write(ref _status, _executed);
            Close();
        }
예제 #18
0
        /// <summary>
        /// Removes the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>
        ///   <c>true</c> if the specified key was removed; otherwise, <c>false</c>.
        /// </returns>
        public bool Remove(TKey key)
        {
            bool result = false;
            int  revision;

            while (true)
            {
                revision = _revision;
                if (IsOperationSafe())
                {
                    var  entries = ThreadingHelper.VolatileRead(ref _entriesNew);
                    bool done    = false;
                    try
                    {
                        if (RemoveExtracted(key, entries))
                        {
                            result = true;
                        }
                    }
                    finally
                    {
                        var isOperationSafe = IsOperationSafe(entries, revision);
                        if (isOperationSafe)
                        {
                            if (result)
                            {
                                Interlocked.Decrement(ref _count);
                            }
                            done = true;
                        }
                    }
                    if (done)
                    {
                        return(result);
                    }
                }
                else
                {
                    CooperativeGrow();
                }
            }
        }
예제 #19
0
 private bool CanWrite()
 {
     if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread))
     {
         Interlocked.Increment(ref _writeCount);
         return(true);
     }
     if (Interlocked.CompareExchange(ref _master, -1, 0) == 0)
     {
         _freeToRead.Reset();
         // --
         if (Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null) == null)
         {
             // Success
             Interlocked.Increment(ref _writeCount);
             return(true);
         }
     }
     return(false);
 }
예제 #20
0
 public Timeout(Action callback, long dueTime, CancellationToken token)
 {
     if (callback == null)
     {
         throw new NullReferenceException("callback");
     }
     _start = ThreadingHelper.TicksNow();
     if (token.IsCancellationRequested)
     {
         _callback = null;
         _wrapped  = null;
     }
     else
     {
         _callback = callback;
         Initialize(dueTime);
         token.Register(Cancel);
     }
     _hashcode = unchecked ((int)DateTime.Now.Ticks);
 }
예제 #21
0
        /// <summary>
        /// Attempts to retrieve and remove the next item from the back.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns>
        ///   <c>true</c> if the item was taken; otherwise, <c>false</c>.
        /// </returns>
        public bool TryDequeue(out T item)
        {
            item = default(T);
            bool result = false;

            while (true)
            {
                if (IsOperationSafe())
                {
                    var  entries = ThreadingHelper.VolatileRead(ref _entriesNew);
                    bool done    = false;
                    try
                    {
                        Interlocked.Increment(ref _workingThreads);
                        T tmpItem;
                        if (entries.TryDequeue(out tmpItem))
                        {
                            item   = tmpItem;
                            result = true;
                        }
                    }
                    finally
                    {
                        Interlocked.Decrement(ref _workingThreads);
                        if (result)
                        {
                            Interlocked.Decrement(ref _count);
                        }
                        done = true;
                    }
                    if (done)
                    {
                        return(result);
                    }
                }
                else
                {
                    CooperativeGrow();
                }
            }
        }
예제 #22
0
        /// <summary>
        /// Tries to retrieve the item at the specified index.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="item">The item.</param>
        /// <returns>
        ///   <c>true</c> if the item was retrieved; otherwise, <c>false</c>.
        /// </returns>
        public bool TryGet(int index, out T item)
        {
            item = default(T);
            bool result = false;
            int  revision;

            while (true)
            {
                revision = _revision;
                if (IsOperationSafe())
                {
                    var  entries = ThreadingHelper.VolatileRead(ref _entriesNew);
                    bool done    = false;
                    try
                    {
                        T tmpItem;
                        if (TryGetExtracted(index, entries, out tmpItem))
                        {
                            item   = tmpItem;
                            result = true;
                        }
                    }
                    finally
                    {
                        var isOperationSafe = IsOperationSafe(entries, revision);
                        if (isOperationSafe)
                        {
                            done = true;
                        }
                    }
                    if (done)
                    {
                        return(result);
                    }
                }
                else
                {
                    CooperativeGrow();
                }
            }
        }
예제 #23
0
        private bool CanUpgrade()
        {
            if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread))
            {
                Interlocked.Increment(ref _writeCount);
                return(true);
            }
            var check = Interlocked.CompareExchange(ref _master, -2, 1);

            if (check == 1)
            {
                _freeToRead.Reset();
                // --
                if (Thread.VolatileRead(ref _readCount) <= _currentReadingCount.Value && Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null) == null)
                {
                    Thread.VolatileWrite(ref _master, -1);
                    Interlocked.Increment(ref _writeCount);
                    return(true);
                }
            }
            return(false);
        }
예제 #24
0
 private void DoneRead()
 {
     if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread))
     {
         Interlocked.Decrement(ref _readCount);
     }
     else
     {
         if (Thread.VolatileRead(ref _master) < 0)
         {
             if (Interlocked.Decrement(ref _readCount) <= Thread.VolatileRead(ref _edge))
             {
                 Thread.VolatileWrite(ref _master, 0);
                 _freeToWrite.Set();
             }
         }
         else
         {
             Interlocked.Decrement(ref _readCount);
         }
     }
 }
예제 #25
0
        /// <summary>
        /// Determines whether the specified key is contained.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>
        ///   <c>true</c> if the specified key is contained; otherwise, <c>false</c>.
        /// </returns>
        public bool ContainsKey(TKey key)
        {
            bool result = false;
            int  revision;

            while (true)
            {
                revision = _revision;
                if (IsOperationSafe())
                {
                    var  entries = ThreadingHelper.VolatileRead(ref _entriesNew);
                    bool done    = false;
                    try
                    {
                        if (ContainsKeyExtracted(key, entries))
                        {
                            result = true;
                        }
                    }
                    finally
                    {
                        var isOperationSafe = IsOperationSafe(entries, revision);
                        if (isOperationSafe)
                        {
                            done = true;
                        }
                    }
                    if (done)
                    {
                        return(result);
                    }
                }
                else
                {
                    CooperativeGrow();
                }
            }
        }
예제 #26
0
        private bool WaitUpgrade()
        {
            var owner = ThreadingHelper.VolatileRead(ref _ownerThread);

            if (owner == null || owner == Thread.CurrentThread)
            {
                var check = 1;
                while (true)
                {
                    switch (check)
                    {
                    case -2:
                        // Write mode already requested
                        // We are going to steal it
                        // Reserve the lock - so no other writer can take it
                        owner = Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null);
                        if (owner == null || owner == Thread.CurrentThread)
                        {
                            // Set the edge
                            Thread.VolatileWrite(ref _edge, _currentReadingCount.Value);
                        }
                        else
                        {
                            // It was reserved by another thread - abort mission
                            return(false);
                        }
                        if (Thread.VolatileRead(ref _readCount) > Thread.VolatileRead(ref _edge))
                        {
                            // We still need every other reader to finish
                            _freeToWrite.Wait();
                            check = Interlocked.CompareExchange(ref _master, -1, 0);
                        }
                        else
                        {
                            // None to wait
                            Thread.VolatileWrite(ref _master, -1);
                            check = -1;
                        }
                        break;

                    case -1:
                        // There is a writer
                        // Abort mission
                        _freeToRead.Reset();
                        Interlocked.Increment(ref _writeCount);
                        return(true);

                    case 0:
                        // Free to proceed
                        return(true);

                    case 1:
                        // There are readers currently - of course, current thread is a reader
                        // Requesting write mode
                        check = Interlocked.CompareExchange(ref _master, -2, 1);
                        if (check == 1)
                        {
                            _freeToRead.Reset();
                            check = -2;
                        }
                        break;
                    }
                }
            }
            return(false);
        }
예제 #27
0
        /// <summary>
        /// Attempts to add the specified key and associated value.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <returns>The value found in the destination after the attempt, regardless of collisions.</returns>
        public TValue TryAdd(TKey key, TValue value)
        {
            bool result = false;
            int  revision;
            KeyValuePair <TKey, TValue> previous = default(KeyValuePair <TKey, TValue>);
            TValue found = value;

            while (true)
            {
                revision = _revision;
                if (IsOperationSafe())
                {
                    bool isCollision = false;
                    var  entries     = ThreadingHelper.VolatileRead(ref _entriesNew);
                    bool done        = false;
                    try
                    {
                        if (TryAddExtracted(key, value, entries, out previous) != -1)
                        {
                            result = true;
                        }
                        else
                        {
                            isCollision = !_keyComparer.Equals(previous.Key, key);
                        }
                    }
                    finally
                    {
                        var isOperationSafe = IsOperationSafe(entries, revision);
                        if (isOperationSafe)
                        {
                            if (result)
                            {
                                Interlocked.Increment(ref _count);
                                done = true;
                            }
                            else
                            {
                                if (isCollision)
                                {
                                    var oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.GrowRequested, (int)BucketStatus.Free);
                                    if (oldStatus == (int)BucketStatus.Free)
                                    {
                                        _revision++;
                                    }
                                }
                                else
                                {
                                    done  = true;
                                    found = previous.Value;
                                }
                            }
                        }
                    }
                    if (done)
                    {
                        return(found);
                    }
                }
                else
                {
                    CooperativeGrow();
                }
            }
        }
예제 #28
0
 private bool TakeDisposalExecution()
 {
     return(_status != -1 && ThreadingHelper.SpinWaitSetUnless(ref _status, -1, 0, -1));
 }
예제 #29
0
 protected void Start(long dueTime)
 {
     _startTime  = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow());
     _targetTime = _startTime + dueTime;
     _wrapped    = new Timer(Finish, null, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(-1));
 }