public void Dispose()
 {
     if (_lockSource.TryRemoveFromQueue())
     {
         _lockSource = null;
     }
 }
Example #2
0
        public Task <IAsyncReaderWriterLockToken> WriterLockAsync(CancellationToken cancellationToken = default(CancellationToken), ReentrancyToken reentrancyToken = default(ReentrancyToken))
        {
            TaskUtilities.AssertIsOnBackgroundThread();

            var task = ReentrantOrCanceled(true, cancellationToken, reentrancyToken);

            if (task != null)
            {
                return(task);
            }

            var source = new LockSource(this, true);

            _queue.AddWriter(source, out var isFirstWriter);
            if (isFirstWriter)
            {
                source.Release();
            }
            else
            {
                source.RegisterCancellation(cancellationToken);
            }

            return(source.Task);
        }
Example #3
0
 /// <summary>
 /// Adds a reader item
 /// </summary>
 /// <remarks>
 /// 1. R−→R−→R  ―►  R−→R−→R−→R
 ///          ↑               ↑
 ///      _tail           _tail
 ///
 ///
 /// 2.  _wTail       _wTail
 ///          ↓            ↓
 ///    R−→R−→W  ―►  R−→R−→W−→R
 ///          ↑               ↑
 ///      _tail           _tail
 ///
 ///
 /// 3.  _wTail          _wTail
 ///          ↓               ↓
 ///    R−→W−→W−→R  ―►  R−→W−→W−→R−→R
 ///             ↑                  ↑
 ///         _tail              _tail
 /// </remarks>
 /// <param name="item"></param>
 /// <param name="isAddedAfterWriter"></param>
 public void AddReader(LockSource item, out bool isAddedAfterWriter)
 {
     lock (this) {
         UpdateTail(item);
         isAddedAfterWriter = _wTail != null;
     }
 }
Example #4
0
            private LockSource[] FilterAndCopyToArray(LockSource start)
            {
                var count = 0;
                var item  = start;

                while (item != null)
                {
                    if (ReaderCanBeReleased(item))
                    {
                        count++;
                    }
                    item = item.Next;
                }

                var items = new LockSource[count];

                count = 0;
                item  = start;
                while (item != null)
                {
                    if (ReaderCanBeReleased(item))
                    {
                        items[count] = item;
                        count++;
                    }
                    item = item.Next;
                }

                return(items);
            }
Example #5
0
        private void Remove(LockSource lockSource)
        {
            var sourcesToRelease = _queue.Remove(lockSource);

            foreach (var source in sourcesToRelease)
            {
                source.Release();
            }
        }
Example #6
0
            private bool ReaderCanBeReleased(LockSource source)
            {
                var erlSource         = source as ExclusiveReaderLockSource;
                var previousErlSource = source.Previous as ExclusiveReaderLockSource;

                return(erlSource == null ||
                       previousErlSource == null ||
                       erlSource.ExclusiveReaderLock != previousErlSource.ExclusiveReaderLock);
            }
Example #7
0
            private void UpdateTail(LockSource item)
            {
                var tail = Interlocked.Exchange(ref _tail, item);

                if (tail == null)
                {
                    Interlocked.Exchange(ref _head, item);
                }
                else
                {
                    Link(tail, item);
                }
            }
Example #8
0
            private static void Unlink(LockSource item)
            {
                if (item.Next != null)
                {
                    Interlocked.Exchange(ref item.Next.Previous, item.Previous);
                }

                if (item.Previous != null)
                {
                    Interlocked.Exchange(ref item.Previous.Next, item.Next);
                }

                Interlocked.Exchange(ref item.Next, null);
                Interlocked.Exchange(ref item.Previous, null);
            }
Example #9
0
            /// <summary>
            /// Adds a writer item
            /// </summary>
            /// <remarks>
            /// 1.                  _wTail
            ///                          ↓
            ///    R−→R−→R  ―►  R−→R−→R−→W
            ///          ↑               ↑
            ///      _tail           _tail
            ///
            ///
            /// 2.  _wTail          _wTail
            ///          ↓               ↓
            ///    R−→R−→W  ―►  R−→R−→W−→W
            ///          ↑               ↑
            ///      _tail           _tail
            ///
            ///
            /// 3.  _wTail             _wTail
            ///          ↓                  ↓
            ///    R−→W−→W−→R  ―►  R−→W−→W−→W−→R
            ///          ↑                     ↑
            ///      _tail                 _tail
            /// </remarks>
            /// <param name="item"></param>
            /// <param name="isFirstWriter"></param>
            public void AddWriter(LockSource item, out bool isFirstWriter)
            {
                lock (this) {
                    var wTail = Interlocked.Exchange(ref _wTail, item);

                    // Case 1. No writers in the queue. Update _wTail and the _tail
                    // Case 2. No readers in front of a writer, _tail and _wTail point at the same item. Update _wTail.Next, _tail and _wTail
                    if (wTail == null || wTail == _tail)
                    {
                        UpdateTail(item);
                    }
                    else
                    {
                        Link(item, wTail.Next);
                        Link(wTail, item);
                    }

                    isFirstWriter = _head == item;
                }
            }
Example #10
0
            public LockSource[] Remove(LockSource item)
            {
                lock (this) {
                    var next    = item.Next;
                    var oldHead = Interlocked.CompareExchange(ref _head, next, item);

                    var previous = item.Previous;
                    Interlocked.CompareExchange(ref _tail, previous, item);
                    Interlocked.CompareExchange(ref _wTail, previous != null && previous.IsWriter ? previous : null, item);

                    var erLock = (item as ExclusiveReaderLockSource)?.ExclusiveReaderLock;
                    if (erLock != null)
                    {
                        var previousErlSource = previous as ExclusiveReaderLockSource;
                        Interlocked.CompareExchange(ref erLock.Tail, previousErlSource?.ExclusiveReaderLock == erLock ? previousErlSource : null, item);
                    }

                    Unlink(item);
                    if (_head == null)
                    {
                        return(new LockSource[0]);
                    }

                    if (_head.IsWriter && item == oldHead)
                    {
                        return(new[] { _head });
                    }

                    if (_wTail == null && next != null)
                    {
                        return(FilterAndCopyToArray(next));
                    }

                    if (erLock != null)
                    {
                        return(FindFirstExclusiveReader(erLock));
                    }

                    return(new LockSource[0]);
                }
            }
            /// <summary>
            /// Adds a writer item
            /// </summary>
            /// <remarks>
            /// 1.                  _wTail
            ///                          ↓
            ///    R−→R−→R  ―►  R−→R−→R−→W
            ///          ↑               ↑
            ///      _tail           _tail
            /// 
            /// 
            /// 2.  _wTail          _wTail
            ///          ↓               ↓
            ///    R−→R−→W  ―►  R−→R−→W−→W
            ///          ↑               ↑
            ///      _tail           _tail
            /// 
            /// 
            /// 3.  _wTail             _wTail
            ///          ↓                  ↓
            ///    R−→W−→W−→R  ―►  R−→W−→W−→W−→R
            ///          ↑                     ↑
            ///      _tail                 _tail
            /// </remarks>
            /// <param name="item"></param>
            /// <param name="isFirstWriter"></param>
            public void AddWriter(LockSource item, out bool isFirstWriter) {
                lock (this) {
                    var wTail = Interlocked.Exchange(ref _wTail, item);

                    // Case 1. No writers in the queue. Update _wTail and the _tail
                    // Case 2. No readers in front of a writer, _tail and _wTail point at the same item. Update _wTail.Next, _tail and _wTail
                    if (wTail == null || wTail == _tail) {
                        UpdateTail(item);
                    } else {
                        Link(item, wTail.Next);
                        Link(wTail, item);
                    }

                    isFirstWriter = _head == item;
                }
            }
Example #12
0
 private static void Link(LockSource previous, LockSource next)
 {
     Interlocked.Exchange(ref previous.Next, next);
     Interlocked.Exchange(ref next.Previous, previous);
 }
 /// <summary>
 /// Adds a reader item
 /// </summary>
 /// <remarks>
 /// 1. R−→R−→R  ―►  R−→R−→R−→R
 ///          ↑               ↑
 ///      _tail           _tail
 /// 
 /// 
 /// 2.  _wTail       _wTail
 ///          ↓            ↓
 ///    R−→R−→W  ―►  R−→R−→W−→R
 ///          ↑               ↑
 ///      _tail           _tail
 /// 
 /// 
 /// 3.  _wTail          _wTail
 ///          ↓               ↓
 ///    R−→W−→W−→R  ―►  R−→W−→W−→R−→R
 ///             ↑                  ↑
 ///         _tail              _tail
 /// </remarks>
 /// <param name="item"></param>
 /// <param name="isAddedAfterWriter"></param>
 public void AddReader(LockSource item, out bool isAddedAfterWriter) {
     lock (this) {
         UpdateTail(item);
         isAddedAfterWriter = _wTail != null;
     }
 }
            private static void Unlink(LockSource item) {
                if (item.Next != null) {
                    Interlocked.Exchange(ref item.Next.Previous, item.Previous);
                }

                if (item.Previous != null) {
                    Interlocked.Exchange(ref item.Previous.Next, item.Next);
                }

                Interlocked.Exchange(ref item.Next, null);
                Interlocked.Exchange(ref item.Previous, null);
            }
 private static void Link(LockSource previous, LockSource next) {
     Interlocked.Exchange(ref previous.Next, next);
     Interlocked.Exchange(ref next.Previous, previous);
 }
 private bool ReaderCanBeReleased(LockSource source) {
     var erlSource = source as ExclusiveReaderLockSource;
     var previousErlSource = source.Previous as ExclusiveReaderLockSource;
     return erlSource == null 
         || previousErlSource == null 
         || erlSource.ExclusiveReaderLock != previousErlSource.ExclusiveReaderLock;
 }
            private LockSource[] FilterAndCopyToArray(LockSource start) {
                var count = 0;
                var item = start;
                while (item != null) {
                    if (ReaderCanBeReleased(item)) {
                        count++;
                    }
                    item = item.Next;
                }

                var items = new LockSource[count];
                count = 0;
                item = start;
                while (item != null) {
                    if (ReaderCanBeReleased(item)) {
                        items[count] = item;
                        count++;
                    }
                    item = item.Next;
                }

                return items;
            }
 private void UpdateTail(LockSource item) {
     var tail = Interlocked.Exchange(ref _tail, item);
     if (tail == null) {
         Interlocked.Exchange(ref _head, item);
     } else {
         Link(tail, item);
     }
 }
            public LockSource[] Remove(LockSource item) {
                lock (this) {
                    var next = item.Next;
                    var oldHead = Interlocked.CompareExchange(ref _head, next, item);

                    var previous = item.Previous;
                    Interlocked.CompareExchange(ref _tail, previous, item);
                    Interlocked.CompareExchange(ref _wTail, previous != null && previous.IsWriter ? previous : null, item);

                    var erLock = (item as ExclusiveReaderLockSource)?.ExclusiveReaderLock;
                    if (erLock != null) {
                        var previousErlSource = previous as ExclusiveReaderLockSource;
                        Interlocked.CompareExchange(ref erLock.Tail, previousErlSource?.ExclusiveReaderLock == erLock ? previousErlSource : null, item);
                    }
                    
                    Unlink(item);
                    if (_head == null) {
                        return new LockSource[0];
                    }

                    if (_head.IsWriter && item == oldHead) {
                        return new[] { _head };
                    }

                    if (_wTail == null && next != null) {
                        return FilterAndCopyToArray(next);
                    }

                    if (erLock != null) {
                        return FindFirstExclusiveReader(erLock);
                    }

                    return new LockSource[0];
                }
            }
 public void Dispose() {
     if (_lockSource.TryRemoveFromQueue()) {
         _lockSource = null;
     }
 }
 public Token(LockSource lockSource)
 {
     _lockSource = lockSource;
     Reentrancy  = LockTokenFactory.Create(lockSource);
 }
 public Token(LockSource lockSource) {
     _lockSource = lockSource;
     Reentrancy = LockTokenFactory.Create(lockSource);
 }