コード例 #1
0
        /// <inheritdoc />
        public async Task <IDisposable> AquireEntityLockAsync(NetworkEntityGuid guid)
        {
            //basically, root lock so nobody can change the entity state until we're done.
            //We lock read globally and then write for the entity

            IDisposable root  = null;
            IDisposable child = null;

            try
            {
                //TODO: It's POSSIBLE, but unlikely that the entity was removed. Or that they didn't check?
                root = await InternalGlobalLock.ReaderLockAsync().ConfigureAwait(false);

                if (!EntityRefCountingMap.ContainsKey(guid.RawGuidValue))
                {
                    throw new InvalidOperationException($"Entity: {guid} does not exist in the locking service.");
                }

                //TODO: Should we do a write lock?
                child = await EntityLockingObjectMap[guid.RawGuidValue].WriterLockAsync().ConfigureAwait(false);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                child?.Dispose();
                root?.Dispose();
            }

            //MUST dispose this to dispose the locks.
            return(new AggregateDisposableLock(root, child));
        }
コード例 #2
0
 /// <inheritdoc />
 public async Task <bool> ContainsLockingServiceForAsync(NetworkEntityGuid guid)
 {
     using (await InternalGlobalLock.ReaderLockAsync().ConfigureAwait(false))
     {
         //We don't need to check value.
         return(EntityRefCountingMap.ContainsKey(guid.RawGuidValue));
     }
 }
コード例 #3
0
 /// <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();
         }
     }
 }
コード例 #4
0
        /// <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;
            }
        }
コード例 #5
0
        /// <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());
        }