LocationComponent.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using MongoDB.Bson.Serialization.Attributes;
  5. namespace ETModel
  6. {
  7. public abstract class LocationTask: Component
  8. {
  9. public abstract void Run();
  10. }
  11. [ObjectSystem]
  12. public class LocationQueryTaskAwakeSystem : AwakeSystem<LocationQueryTask, long>
  13. {
  14. public override void Awake(LocationQueryTask self, long key)
  15. {
  16. self.Key = key;
  17. self.Tcs = new TaskCompletionSource<long>();
  18. }
  19. }
  20. public sealed class LocationQueryTask : LocationTask
  21. {
  22. public long Key;
  23. public TaskCompletionSource<long> Tcs;
  24. public Task<long> Task
  25. {
  26. get
  27. {
  28. return this.Tcs.Task;
  29. }
  30. }
  31. public override void Run()
  32. {
  33. try
  34. {
  35. LocationComponent locationComponent = this.GetParent<LocationComponent>();
  36. long location = locationComponent.Get(this.Key);
  37. this.Tcs.SetResult(location);
  38. }
  39. catch (Exception e)
  40. {
  41. this.Tcs.SetException(e);
  42. }
  43. }
  44. }
  45. public class LocationComponent : Component
  46. {
  47. private readonly Dictionary<long, long> locations = new Dictionary<long, long>();
  48. private readonly Dictionary<long, long> lockDict = new Dictionary<long, long>();
  49. private readonly Dictionary<long, Queue<LocationTask>> taskQueues = new Dictionary<long, Queue<LocationTask>>();
  50. public void Add(long key, long instanceId)
  51. {
  52. this.locations[key] = instanceId;
  53. Log.Info($"location add key: {key} instanceId: {instanceId}");
  54. // 更新db
  55. //await Game.Scene.GetComponent<DBProxyComponent>().Save(new Location(key, address));
  56. }
  57. public void Remove(long key)
  58. {
  59. Log.Info($"location remove key: {key}");
  60. this.locations.Remove(key);
  61. }
  62. public long Get(long key)
  63. {
  64. this.locations.TryGetValue(key, out long instanceId);
  65. return instanceId;
  66. }
  67. public async void Lock(long key, long instanceId, int time = 0)
  68. {
  69. if (this.lockDict.ContainsKey(key))
  70. {
  71. Log.Error($"不可能同时存在两次lock, key: {key} InstanceId: {instanceId}");
  72. return;
  73. }
  74. Log.Info($"location lock key: {key} InstanceId: {instanceId}");
  75. if (!this.locations.TryGetValue(key, out long saveInstanceId))
  76. {
  77. Log.Error($"actor没有注册, key: {key} InstanceId: {instanceId}");
  78. return;
  79. }
  80. if (saveInstanceId != instanceId)
  81. {
  82. Log.Error($"actor注册的instanceId与lock的不一致, key: {key} InstanceId: {instanceId} saveInstanceId: {saveInstanceId}");
  83. return;
  84. }
  85. this.lockDict.Add(key, instanceId);
  86. // 超时则解锁
  87. if (time > 0)
  88. {
  89. await Game.Scene.GetComponent<TimerComponent>().WaitAsync(time);
  90. if (!this.lockDict.ContainsKey(key))
  91. {
  92. return;
  93. }
  94. Log.Info($"location timeout unlock key: {key} time: {time}");
  95. this.UnLock(key);
  96. }
  97. }
  98. public void UnLockAndUpdate(long key, long oldInstanceId, long instanceId)
  99. {
  100. this.lockDict.TryGetValue(key, out long lockInstanceId);
  101. if (lockInstanceId != oldInstanceId)
  102. {
  103. Log.Error($"unlock appid is different {lockInstanceId} {oldInstanceId}" );
  104. }
  105. Log.Info($"location unlock key: {key} oldInstanceId: {oldInstanceId} new: {instanceId}");
  106. this.locations[key] = instanceId;
  107. this.UnLock(key);
  108. }
  109. private void UnLock(long key)
  110. {
  111. this.lockDict.Remove(key);
  112. if (!this.taskQueues.TryGetValue(key, out Queue<LocationTask> tasks))
  113. {
  114. return;
  115. }
  116. while (true)
  117. {
  118. if (tasks.Count <= 0)
  119. {
  120. this.taskQueues.Remove(key);
  121. return;
  122. }
  123. if (this.lockDict.ContainsKey(key))
  124. {
  125. return;
  126. }
  127. LocationTask task = tasks.Dequeue();
  128. try
  129. {
  130. task.Run();
  131. }
  132. catch (Exception e)
  133. {
  134. Log.Error(e);
  135. }
  136. task.Dispose();
  137. }
  138. }
  139. public Task<long> GetAsync(long key)
  140. {
  141. if (!this.lockDict.ContainsKey(key))
  142. {
  143. this.locations.TryGetValue(key, out long instanceId);
  144. Log.Info($"location get key: {key} {instanceId}");
  145. return Task.FromResult(instanceId);
  146. }
  147. LocationQueryTask task = ComponentFactory.CreateWithParent<LocationQueryTask, long>(this, key);
  148. this.AddTask(key, task);
  149. return task.Task;
  150. }
  151. public void AddTask(long key, LocationTask task)
  152. {
  153. if (!this.taskQueues.TryGetValue(key, out Queue<LocationTask> tasks))
  154. {
  155. tasks = new Queue<LocationTask>();
  156. this.taskQueues[key] = tasks;
  157. }
  158. tasks.Enqueue(task);
  159. }
  160. public override void Dispose()
  161. {
  162. if (this.IsDisposed)
  163. {
  164. return;
  165. }
  166. base.Dispose();
  167. this.locations.Clear();
  168. this.lockDict.Clear();
  169. this.taskQueues.Clear();
  170. }
  171. }
  172. }