/// <inheritdoc /> public async Task RegisterEntityInterestAsync(NetworkEntityGuid guid) { using (await InternalGlobalLock.WriterLockAsync().ConfigureAwait(false)) { if (EntityRefCountingMap.ContainsKey(guid.RawGuidValue)) { EntityRefCountingMap[guid.RawGuidValue]++; } else { EntityRefCountingMap[guid.RawGuidValue] = 1; EntityLockingObjectMap[guid.RawGuidValue] = new AsyncReaderWriterLock(); } } }
/// <inheritdoc /> public async Task ReleaseEntityInterestAsync(NetworkEntityGuid guid) { using (await InternalGlobalLock.WriterLockAsync().ConfigureAwait(false)) { if (EntityRefCountingMap.ContainsKey(guid.RawGuidValue)) { EntityRefCountingMap[guid.RawGuidValue]--; if (EntityRefCountingMap[guid.RawGuidValue] <= 0) { EntityLockingObjectMap.Remove(guid.RawGuidValue, out var locker); EntityRefCountingMap.Remove(guid.RawGuidValue, out int val); } } //TODO: Should we throw if they try when it doesn't even know the entity? return; } }
/// <inheritdoc /> public async Task <FinalEntityLockResult> TryAquireFinalEntityLockAsync(NetworkEntityGuid guid) { IDisposable root = null; IDisposable childLock = null; try { root = await InternalGlobalLock.WriterLockAsync().ConfigureAwait(false); if (!EntityRefCountingMap.ContainsKey(guid.RawGuidValue)) { return(new FinalEntityLockResult()); } if (EntityRefCountingMap[guid.RawGuidValue] == 1) { childLock = await EntityLockingObjectMap[guid.RawGuidValue].WriterLockAsync().ConfigureAwait(false); //On the disposable of the lock we should clear up the entity entry. return(new FinalEntityLockResult(new DisposableEventDispatcherDecorator(new AggregateDisposableLock(root, childLock), () => { EntityRefCountingMap.Remove(guid.RawGuidValue, out var val1); EntityLockingObjectMap.Remove(guid.RawGuidValue, out var val2); }))); } } catch (Exception e) { throw; } finally { childLock?.Dispose(); root?.Dispose(); } return(new FinalEntityLockResult()); }