|
|
@@ -1,201 +1,129 @@
|
|
|
-using System;
|
|
|
-using System.Collections.Generic;
|
|
|
+using System.Collections.Generic;
|
|
|
|
|
|
namespace ETModel
|
|
|
{
|
|
|
- public abstract class LocationTask: Component
|
|
|
- {
|
|
|
- public abstract void Run();
|
|
|
- }
|
|
|
-
|
|
|
[ObjectSystem]
|
|
|
- public class LocationQueryTaskAwakeSystem : AwakeSystem<LocationQueryTask, long>
|
|
|
+ public class LockInfoAwakeSystem : AwakeSystem<LockInfo, long, CoroutineLock>
|
|
|
{
|
|
|
- public override void Awake(LocationQueryTask self, long key)
|
|
|
+ public override void Awake(LockInfo self, long lockInstanceId, CoroutineLock coroutineLock)
|
|
|
{
|
|
|
- self.Key = key;
|
|
|
- self.Tcs = new ETTaskCompletionSource<long>();
|
|
|
+ self.LockInstanceId = lockInstanceId;
|
|
|
+ self.CoroutineLock = coroutineLock;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- public sealed class LocationQueryTask : LocationTask
|
|
|
+
|
|
|
+ public class LockInfo: Component
|
|
|
{
|
|
|
- public long Key;
|
|
|
-
|
|
|
- public ETTaskCompletionSource<long> Tcs;
|
|
|
-
|
|
|
- public ETTask<long> Task
|
|
|
- {
|
|
|
- get
|
|
|
- {
|
|
|
- return this.Tcs.Task;
|
|
|
- }
|
|
|
- }
|
|
|
+ public long LockInstanceId;
|
|
|
+
|
|
|
+ public CoroutineLock CoroutineLock;
|
|
|
|
|
|
- public override void Run()
|
|
|
+ public override void Dispose()
|
|
|
{
|
|
|
- try
|
|
|
- {
|
|
|
- LocationComponent locationComponent = this.GetParent<LocationComponent>();
|
|
|
- long location = locationComponent.Get(this.Key);
|
|
|
- this.Tcs.SetResult(location);
|
|
|
- }
|
|
|
- catch (Exception e)
|
|
|
- {
|
|
|
- this.Tcs.SetException(e);
|
|
|
- }
|
|
|
+ this.LockInstanceId = 0;
|
|
|
+ this.CoroutineLock.Dispose();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public class LocationComponent : Component
|
|
|
{
|
|
|
private readonly Dictionary<long, long> locations = new Dictionary<long, long>();
|
|
|
|
|
|
- private readonly Dictionary<long, long> lockDict = new Dictionary<long, long>();
|
|
|
-
|
|
|
- private readonly Dictionary<long, Queue<LocationTask>> taskQueues = new Dictionary<long, Queue<LocationTask>>();
|
|
|
-
|
|
|
- public void Add(long key, long instanceId)
|
|
|
+ private readonly Dictionary<long, LockInfo> lockInfos = new Dictionary<long, LockInfo>();
|
|
|
+
|
|
|
+ public override void Dispose()
|
|
|
{
|
|
|
- this.locations[key] = instanceId;
|
|
|
-
|
|
|
- Log.Info($"location add key: {key} instanceId: {instanceId}");
|
|
|
+ if (this.IsDisposed)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ base.Dispose();
|
|
|
+
|
|
|
+ this.locations.Clear();
|
|
|
|
|
|
- // 更新db
|
|
|
- //await Game.Scene.GetComponent<DBProxyComponent>().Save(new Location(key, address));
|
|
|
+ foreach (LockInfo lockInfo in this.lockInfos.Values)
|
|
|
+ {
|
|
|
+ lockInfo.Dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ this.lockInfos.Clear();
|
|
|
}
|
|
|
|
|
|
- public void Remove(long key)
|
|
|
+ public async ETTask Add(long key, long instanceId)
|
|
|
{
|
|
|
- Log.Info($"location remove key: {key}");
|
|
|
- this.locations.Remove(key);
|
|
|
+ using (await CoroutineLockComponent.Instance.Wait(key + (int)AppType.Location))
|
|
|
+ {
|
|
|
+ this.locations[key] = instanceId;
|
|
|
+ Log.Info($"location add key: {key} instanceId: {instanceId}");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public long Get(long key)
|
|
|
+ public async ETTask Remove(long key)
|
|
|
{
|
|
|
- this.locations.TryGetValue(key, out long instanceId);
|
|
|
- return instanceId;
|
|
|
+ using (await CoroutineLockComponent.Instance.Wait(key + (int)AppType.Location))
|
|
|
+ {
|
|
|
+ this.locations.Remove(key);
|
|
|
+ Log.Info($"location remove key: {key}");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public async ETVoid Lock(long key, long instanceId, int time = 0)
|
|
|
+ public async ETTask<long> Get(long key)
|
|
|
{
|
|
|
- if (this.lockDict.ContainsKey(key))
|
|
|
+ using (await CoroutineLockComponent.Instance.Wait(key + (int)AppType.Location))
|
|
|
{
|
|
|
- Log.Error($"不可能同时存在两次lock, key: {key} InstanceId: {instanceId}");
|
|
|
- return;
|
|
|
+ this.locations.TryGetValue(key, out long instanceId);
|
|
|
+ Log.Info($"location get key: {key} {instanceId}");
|
|
|
+ return instanceId;
|
|
|
}
|
|
|
|
|
|
- Log.Info($"location lock key: {key} InstanceId: {instanceId}");
|
|
|
+ }
|
|
|
|
|
|
+ public async ETVoid Lock(long key, long instanceId, int time = 0)
|
|
|
+ {
|
|
|
if (!this.locations.TryGetValue(key, out long saveInstanceId))
|
|
|
{
|
|
|
Log.Error($"actor没有注册, key: {key} InstanceId: {instanceId}");
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (saveInstanceId != instanceId)
|
|
|
{
|
|
|
Log.Error($"actor注册的instanceId与lock的不一致, key: {key} InstanceId: {instanceId} saveInstanceId: {saveInstanceId}");
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
+ CoroutineLock coroutineLock = await CoroutineLockComponent.Instance.Wait(key + (int)AppType.Location);
|
|
|
|
|
|
- this.lockDict.Add(key, instanceId);
|
|
|
+ LockInfo lockInfo = ComponentFactory.Create<LockInfo, long, CoroutineLock>(instanceId, coroutineLock);
|
|
|
+
|
|
|
+ this.lockInfos.Add(key, lockInfo);
|
|
|
+
|
|
|
+ Log.Info($"location lock key: {key} InstanceId: {instanceId}");
|
|
|
|
|
|
// 超时则解锁
|
|
|
if (time > 0)
|
|
|
{
|
|
|
await Game.Scene.GetComponent<TimerComponent>().WaitAsync(time);
|
|
|
-
|
|
|
- if (!this.lockDict.ContainsKey(key))
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
- Log.Info($"location timeout unlock key: {key} time: {time}");
|
|
|
- this.UnLock(key);
|
|
|
+ this.UnLock(key, instanceId, instanceId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void UnLockAndUpdate(long key, long oldInstanceId, long instanceId)
|
|
|
+ public void UnLock(long key, long oldInstanceId, long newInstanceId)
|
|
|
{
|
|
|
- this.lockDict.TryGetValue(key, out long lockInstanceId);
|
|
|
- if (lockInstanceId != oldInstanceId)
|
|
|
- {
|
|
|
- Log.Error($"unlock appid is different {lockInstanceId} {oldInstanceId}" );
|
|
|
- }
|
|
|
- Log.Info($"location unlock key: {key} oldInstanceId: {oldInstanceId} new: {instanceId}");
|
|
|
- this.locations[key] = instanceId;
|
|
|
- this.UnLock(key);
|
|
|
- }
|
|
|
-
|
|
|
- private void UnLock(long key)
|
|
|
- {
|
|
|
- this.lockDict.Remove(key);
|
|
|
-
|
|
|
- if (!this.taskQueues.TryGetValue(key, out Queue<LocationTask> tasks))
|
|
|
+ if (!this.lockInfos.TryGetValue(key, out LockInfo lockInfo))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- while (true)
|
|
|
- {
|
|
|
- if (tasks.Count <= 0)
|
|
|
- {
|
|
|
- this.taskQueues.Remove(key);
|
|
|
- return;
|
|
|
- }
|
|
|
- if (this.lockDict.ContainsKey(key))
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- LocationTask task = tasks.Dequeue();
|
|
|
- try
|
|
|
- {
|
|
|
- task.Run();
|
|
|
- }
|
|
|
- catch (Exception e)
|
|
|
- {
|
|
|
- Log.Error(e);
|
|
|
- }
|
|
|
- task.Dispose();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public ETTask<long> GetAsync(long key)
|
|
|
- {
|
|
|
- if (!this.lockDict.ContainsKey(key))
|
|
|
- {
|
|
|
- this.locations.TryGetValue(key, out long instanceId);
|
|
|
- Log.Info($"location get key: {key} {instanceId}");
|
|
|
- return ETTask.FromResult(instanceId);
|
|
|
- }
|
|
|
-
|
|
|
- LocationQueryTask task = ComponentFactory.CreateWithParent<LocationQueryTask, long>(this, key);
|
|
|
- this.AddTask(key, task);
|
|
|
- return task.Task;
|
|
|
- }
|
|
|
-
|
|
|
- public void AddTask(long key, LocationTask task)
|
|
|
- {
|
|
|
- if (!this.taskQueues.TryGetValue(key, out Queue<LocationTask> tasks))
|
|
|
- {
|
|
|
- tasks = new Queue<LocationTask>();
|
|
|
- this.taskQueues[key] = tasks;
|
|
|
- }
|
|
|
- tasks.Enqueue(task);
|
|
|
- }
|
|
|
-
|
|
|
- public override void Dispose()
|
|
|
- {
|
|
|
- if (this.IsDisposed)
|
|
|
+ if (lockInfo.LockInstanceId != oldInstanceId)
|
|
|
{
|
|
|
+ Log.Error($"unlock appid is different {lockInfo.LockInstanceId} {oldInstanceId}" );
|
|
|
return;
|
|
|
}
|
|
|
- base.Dispose();
|
|
|
+ Log.Info($"location unlock key: {key} oldInstanceId: {oldInstanceId} new: {newInstanceId}");
|
|
|
|
|
|
- this.locations.Clear();
|
|
|
- this.lockDict.Clear();
|
|
|
- this.taskQueues.Clear();
|
|
|
+ this.locations[key] = newInstanceId;
|
|
|
+ lockInfo.Dispose();
|
|
|
}
|
|
|
}
|
|
|
}
|