public bool TryAcquireLockEntry(InMemoryConnection connection, string resource, out LockEntry entry) { var acquired = false; lock (_state._locks) { if (!_state._locks.TryGetValue(resource, out entry)) { _state._locks.Add(resource, entry = new LockEntry { Owner = connection, ReferenceCount = 1, Level = 1 }); acquired = true; } else if (entry.Owner == connection) { entry.Level++; acquired = true; } // TODO: Ensure ReferenceCount is updated only under _state._locks entry.ReferenceCount++; } return(acquired); }
public LockDisposable(InMemoryDispatcherBase dispatcher, InMemoryConnection reference, string resource, LockEntry entry) { _dispatcher = dispatcher; _reference = reference; _resource = resource; _entry = entry ?? throw new ArgumentNullException(nameof(entry)); }
public void CancelLockEntry(string resource, LockEntry entry) { lock (_state._locks) { if (!_state._locks.TryGetValue(resource, out var current2) || !ReferenceEquals(current2, entry)) { throw new InvalidOperationException("Precondition failed when decrementing a lock"); } entry.ReferenceCount--; if (entry.ReferenceCount == 0) { _state._locks.Remove(resource); } } }
public void ReleaseLockEntry(InMemoryConnection connection, string resource, LockEntry entry) { // TODO: Ensure lock ordering to avoid deadlocks lock (_state._locks) { if (!_state._locks.TryGetValue(resource, out var current)) { throw new InvalidOperationException("Does not contain a lock"); } if (!ReferenceEquals(current, entry)) { throw new InvalidOperationException("Does not contain a correct lock entry"); } lock (entry) { if (!ReferenceEquals(entry.Owner, connection)) { throw new InvalidOperationException("Wrong entry owner"); } if (entry.Level <= 0) { throw new InvalidOperationException("Wrong level"); } entry.Level--; if (entry.Level == 0) { entry.Owner = null; entry.ReferenceCount--; if (entry.ReferenceCount == 0) { _state._locks.Remove(resource); } else { Monitor.Pulse(entry); } } } } }