public void Dispose() { if (_lockSource.TryRemoveFromQueue()) { _lockSource = null; } }
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); }
/// <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 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 Remove(LockSource lockSource) { var sourcesToRelease = _queue.Remove(lockSource); foreach (var source in sourcesToRelease) { source.Release(); } }
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 void UpdateTail(LockSource item) { var tail = Interlocked.Exchange(ref _tail, item); if (tail == null) { Interlocked.Exchange(ref _head, item); } else { Link(tail, item); } }
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); }
/// <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; } }
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; } }
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); }