using System.Collections.Generic; namespace ET { [ObjectSystem] public class LockInfoAwakeSystem: AwakeSystem { public override void Awake(LockInfo self, long lockInstanceId, CoroutineLock coroutineLock) { self.CoroutineLock = coroutineLock; self.LockInstanceId = lockInstanceId; } } public class LockInfo: Entity { public long LockInstanceId; public CoroutineLock CoroutineLock; public override void Dispose() { if (this.IsDisposed) { return; } base.Dispose(); this.CoroutineLock.Dispose(); LockInstanceId = 0; } } public class LocationComponent: Entity { public readonly Dictionary locations = new Dictionary(); private readonly Dictionary lockInfos = new Dictionary(); public async ETTask Add(long key, long instanceId) { using (await CoroutineLockComponent.Instance.Wait(CoroutineLockType.Location, key)) { this.locations[key] = instanceId; Log.Debug($"location add key: {key} instanceId: {instanceId}"); } } public async ETTask Remove(long key) { using (await CoroutineLockComponent.Instance.Wait(CoroutineLockType.Location, key)) { this.locations.Remove(key); Log.Debug($"location remove key: {key}"); } } public async ETVoid Lock(long key, long instanceId, int time = 0) { CoroutineLock coroutineLock = await CoroutineLockComponent.Instance.Wait(CoroutineLockType.Location, key); LockInfo lockInfo = EntityFactory.Create(this.Domain, instanceId, coroutineLock); lockInfo.Parent = this; this.lockInfos.Add(key, lockInfo); Log.Debug($"location lock key: {key} instanceId: {instanceId}"); if (time > 0) { long lockInfoInstanceId = lockInfo.InstanceId; await TimerComponent.Instance.WaitAsync(time); if (lockInfo.InstanceId != lockInfoInstanceId) { return; } UnLock(key, instanceId, instanceId); } } public void UnLock(long key, long oldInstanceId, long newInstanceId) { if (!this.lockInfos.TryGetValue(key, out LockInfo lockInfo)) { Log.Error($"location unlock not found key: {key} {oldInstanceId}"); return; } if (oldInstanceId != lockInfo.LockInstanceId) { Log.Error($"location unlock oldInstanceId is different: {key} {oldInstanceId}"); return; } Log.Debug($"location unlock key: {key} instanceId: {oldInstanceId} newInstanceId: {newInstanceId}"); this.locations[key] = newInstanceId; this.lockInfos.Remove(key); // 解锁 lockInfo.Dispose(); } public async ETTask Get(long key) { using (await CoroutineLockComponent.Instance.Wait(CoroutineLockType.Location, key)) { this.locations.TryGetValue(key, out long instanceId); Log.Debug($"location get key: {key} instanceId: {instanceId}"); return instanceId; } } public override void Dispose() { if (this.IsDisposed) { return; } base.Dispose(); this.locations.Clear(); this.lockInfos.Clear(); } } }