LockComponentSystem.cs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net;
  4. using System.Threading.Tasks;
  5. using ETModel;
  6. namespace ETHotfix
  7. {
  8. [ObjectSystem]
  9. public class LockComponentAwakeSystem : AwakeSystem<LockComponent, IPEndPoint>
  10. {
  11. public override void Awake(LockComponent self, IPEndPoint a)
  12. {
  13. self.Awake(a);
  14. }
  15. }
  16. /// <summary>
  17. /// 分布式锁组件,Unit对象可能在不同进程上有镜像,访问该对象的时候需要对他加锁
  18. /// </summary>
  19. public static class LockComponentEx
  20. {
  21. public static void Awake(this LockComponent self, IPEndPoint addr)
  22. {
  23. self.address = addr;
  24. }
  25. public static async Task Lock(this LockComponent self)
  26. {
  27. ++self.lockCount;
  28. if (self.status == LockStatus.Locked)
  29. {
  30. return;
  31. }
  32. if (self.status == LockStatus.LockRequesting)
  33. {
  34. await self.WaitLock();
  35. return;
  36. }
  37. self.status = LockStatus.LockRequesting;
  38. // 真身直接本地请求锁,镜像需要调用Rpc获取锁
  39. MasterComponent masterComponent = self.Entity.GetComponent<MasterComponent>();
  40. if (masterComponent != null)
  41. {
  42. await masterComponent.Lock(self.address);
  43. }
  44. else
  45. {
  46. self.RequestLock();
  47. await self.WaitLock();
  48. }
  49. }
  50. private static Task<bool> WaitLock(this LockComponent self)
  51. {
  52. if (self.status == LockStatus.Locked)
  53. {
  54. return Task.FromResult(true);
  55. }
  56. TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
  57. self.queue.Enqueue(tcs);
  58. return tcs.Task;
  59. }
  60. private static async void RequestLock(this LockComponent self)
  61. {
  62. try
  63. {
  64. Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.address);
  65. string serverAddress = StartConfigComponent.Instance.StartConfig.ServerIP;
  66. G2G_LockRequest request = new G2G_LockRequest { Id = self.Entity.Id, Address = serverAddress };
  67. await session.Call(request);
  68. self.status = LockStatus.Locked;
  69. foreach (TaskCompletionSource<bool> taskCompletionSource in self.queue)
  70. {
  71. taskCompletionSource.SetResult(true);
  72. }
  73. self.queue.Clear();
  74. }
  75. catch (Exception e)
  76. {
  77. Log.Error($"获取锁失败: {self.address} {self.Entity.Id} {e}");
  78. }
  79. }
  80. public static async Task Release(this LockComponent self)
  81. {
  82. --self.lockCount;
  83. if (self.lockCount != 0)
  84. {
  85. return;
  86. }
  87. self.status = LockStatus.LockedNot;
  88. Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.address);
  89. G2G_LockReleaseRequest request = new G2G_LockReleaseRequest();
  90. await session.Call(request);
  91. }
  92. }
  93. }