LocationComponent.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. namespace Model
  5. {
  6. public abstract class LocationTask : SceneEntity
  7. {
  8. protected LocationTask()
  9. {
  10. }
  11. protected LocationTask(long id) : base(id)
  12. {
  13. }
  14. public abstract void Run();
  15. }
  16. public sealed class LocationLockTask : LocationTask
  17. {
  18. private readonly long key;
  19. private readonly int time;
  20. private readonly TaskCompletionSource<bool> tcs;
  21. public LocationLockTask(long key, int time)
  22. {
  23. this.key = key;
  24. this.time = time;
  25. this.tcs = new TaskCompletionSource<bool>();
  26. }
  27. public Task<bool> Task
  28. {
  29. get
  30. {
  31. return this.tcs.Task;
  32. }
  33. }
  34. public override void Run()
  35. {
  36. try
  37. {
  38. Scene.GetComponent<LocationComponent>().Lock(this.key, this.time);
  39. this.tcs.SetResult(true);
  40. }
  41. catch (Exception e)
  42. {
  43. this.tcs.SetException(e);
  44. }
  45. }
  46. }
  47. public sealed class LocationQueryTask : LocationTask
  48. {
  49. private readonly long key;
  50. private readonly TaskCompletionSource<int> tcs;
  51. public LocationQueryTask(long key)
  52. {
  53. this.key = key;
  54. this.tcs = new TaskCompletionSource<int>();
  55. }
  56. public Task<int> Task
  57. {
  58. get
  59. {
  60. return this.tcs.Task;
  61. }
  62. }
  63. public override void Run()
  64. {
  65. try
  66. {
  67. int location = Scene.GetComponent<LocationComponent>().Get(key);
  68. this.tcs.SetResult(location);
  69. }
  70. catch (Exception e)
  71. {
  72. this.tcs.SetException(e);
  73. }
  74. }
  75. }
  76. public class LocationComponent : Component
  77. {
  78. private readonly Dictionary<long, int> locations = new Dictionary<long, int>();
  79. private readonly Dictionary<long, int> lockDict = new Dictionary<long, int>();
  80. private readonly Dictionary<long, EQueue<LocationTask>> taskQueues = new Dictionary<long, EQueue<LocationTask>>();
  81. public void Add(long key, int appId)
  82. {
  83. this.locations[key] = appId;
  84. Log.Info($"location add key: {key} appid: {appId}");
  85. // 更新db
  86. //await Game.Scene.GetComponent<DBProxyComponent>().Save(new Location(key, address));
  87. }
  88. public void Remove(long key)
  89. {
  90. Log.Info($"location remove key: {key}");
  91. this.locations.Remove(key);
  92. }
  93. public int Get(long key)
  94. {
  95. this.locations.TryGetValue(key, out int location);
  96. return location;
  97. }
  98. public async void Lock(long key, int appId, int time = 0)
  99. {
  100. if (this.lockDict.ContainsKey(key))
  101. {
  102. return;
  103. }
  104. this.lockDict.Add(key, appId);
  105. // 超时则解锁
  106. if (time > 0)
  107. {
  108. await Game.Scene.GetComponent<TimerComponent>().WaitAsync(time);
  109. int saveAppId = 0;
  110. this.lockDict.TryGetValue(key, out saveAppId);
  111. if (saveAppId != appId)
  112. {
  113. Log.Warning($"unlock appid is different {saveAppId} {appId}");
  114. return;
  115. }
  116. this.UnLock(key);
  117. }
  118. }
  119. public void UpdateAndUnLock(long key, int appId, int value)
  120. {
  121. int saveAppId = 0;
  122. this.lockDict.TryGetValue(key, out saveAppId);
  123. if (saveAppId != appId)
  124. {
  125. Log.Warning($"unlock appid is different {saveAppId} {appId}" );
  126. return;
  127. }
  128. this.Add(key, value);
  129. this.UnLock(key);
  130. }
  131. private void UnLock(long key)
  132. {
  133. this.lockDict.Remove(key);
  134. if (!this.taskQueues.TryGetValue(key, out EQueue<LocationTask> tasks))
  135. {
  136. return;
  137. }
  138. while (true)
  139. {
  140. if (tasks.Count <= 0)
  141. {
  142. this.taskQueues.Remove(key);
  143. return;
  144. }
  145. if (this.lockDict.ContainsKey(key))
  146. {
  147. return;
  148. }
  149. LocationTask task = tasks.Dequeue();
  150. task.Run();
  151. }
  152. }
  153. public Task<bool> LockAsync(long key, int time)
  154. {
  155. if (!this.lockDict.ContainsKey(key))
  156. {
  157. this.Lock(key, time);
  158. return Task.FromResult(true);
  159. }
  160. LocationLockTask task = new LocationLockTask(key, time);
  161. this.AddTask(key, task);
  162. return task.Task;
  163. }
  164. public Task<int> GetAsync(long key)
  165. {
  166. if (!this.lockDict.ContainsKey(key))
  167. {
  168. this.locations.TryGetValue(key, out int location);
  169. Log.Info($"location get key: {key} {location}");
  170. return Task.FromResult(location);
  171. }
  172. LocationQueryTask task = new LocationQueryTask(key);
  173. this.AddTask(key, task);
  174. return task.Task;
  175. }
  176. public void AddTask(long key, LocationTask task)
  177. {
  178. if (!this.taskQueues.TryGetValue(key, out EQueue<LocationTask> tasks))
  179. {
  180. tasks = new EQueue<LocationTask>();
  181. this.taskQueues[key] = tasks;
  182. }
  183. task.Scene = this.GetEntity<Scene>();
  184. tasks.Enqueue(task);
  185. }
  186. public override void Dispose()
  187. {
  188. if (this.Id == 0)
  189. {
  190. return;
  191. }
  192. base.Dispose();
  193. }
  194. }
  195. }