Beispiel #1
0
        //****************************************

        private void Cancel(KeyedLockInstance instance)
        {
            // Retrieve the current lock state
            while (_Locks.TryGetValue(instance.Key !, out var OldQueue))
            {
                // Can get no results (or no queue at all) if
                // - someone releases while we cancel and Release removes us from the queue
                // - we disposed
                if (OldQueue.IsEmpty)
                {
                    return;
                }

                var NewQueue = OldQueue.Remove(instance);

                if (ReferenceEquals(OldQueue, NewQueue))
                {
                    return;
                }

                // Apply the changes to the lock queue
                if (_Locks.TryUpdate(instance.Key !, NewQueue, OldQueue))
                {
                    return;
                }

                // Someone modified the lock queue, probably a new waiter, so retry
            }
        }
Beispiel #2
0
        private void Release(TKey key)
        {
            // Retrieve the current lock state
            while (_Locks.TryGetValue(key, out var OldQueue))
            {
                for (; ;)
                {
                    // If it's empty, there's no waiters or they've all cancelled
                    if (OldQueue.IsEmpty)
                    {
                        // Release the lock
                        if (((IDictionary <TKey, ImmutableList <KeyedLockInstance> >)_Locks).Remove(new KeyValuePair <TKey, ImmutableList <KeyedLockInstance> >(key, OldQueue)))
                        {
                            // If we're disposing and the final held lock, complete disposal
                            if (_Disposer != null && _Locks.IsEmpty)
                            {
                                _Disposer.SwitchToComplete();
                            }

                            return;
                        }

                        // Someone modified the lock queue, probably a new waiter, so retry
                        break;
                    }

                    // Remove the next waiter from the queue
                    var NextWaiter = OldQueue[0];

                    var NewQueue = OldQueue.RemoveAt(0);

                    // Apply the changes to the lock queue
                    if (!_Locks.TryUpdate(key, NewQueue, OldQueue))
                    {
                        // Someone modified the lock queue, probably a new waiter, so retry
                        break;
                    }

                    // Try to activate the waiter
                    if (NextWaiter.TrySwitchToCompleted())
                    {
                        return;
                    }

                    // Waiter has cancelled. Try and pull another off the queue
                    OldQueue = NewQueue;
                }
            }

            // May get here if we dispose
            Debug.Fail("Lock was released but not held");
        }