EventPool.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. //------------------------------------------------------------
  2. // Game Framework
  3. // Copyright © 2013-2021 loyalsoft. All rights reserved.
  4. // Homepage: http://www.game7000.com/
  5. // Feedback: http://www.game7000.com/
  6. //------------------------------------------------------------
  7. using System;
  8. using System.Collections.Generic;
  9. namespace GameFramework
  10. {
  11. /// <summary>
  12. /// 事件池。
  13. /// </summary>
  14. /// <typeparam name="T">事件类型。</typeparam>
  15. internal sealed partial class EventPool<T> where T : BaseEventArgs
  16. {
  17. private readonly GameFrameworkMultiDictionary<int, EventHandler<T>> m_EventHandlers;
  18. private readonly Queue<Event> m_Events;
  19. private readonly Dictionary<object, LinkedListNode<EventHandler<T>>> m_CachedNodes;
  20. private readonly Dictionary<object, LinkedListNode<EventHandler<T>>> m_TempNodes;
  21. private readonly EventPoolMode m_EventPoolMode;
  22. private EventHandler<T> m_DefaultHandler;
  23. /// <summary>
  24. /// 初始化事件池的新实例。
  25. /// </summary>
  26. /// <param name="mode">事件池模式。</param>
  27. public EventPool(EventPoolMode mode)
  28. {
  29. m_EventHandlers = new GameFrameworkMultiDictionary<int, EventHandler<T>>();
  30. m_Events = new Queue<Event>();
  31. m_CachedNodes = new Dictionary<object, LinkedListNode<EventHandler<T>>>();
  32. m_TempNodes = new Dictionary<object, LinkedListNode<EventHandler<T>>>();
  33. m_EventPoolMode = mode;
  34. m_DefaultHandler = null;
  35. }
  36. /// <summary>
  37. /// 获取事件处理函数的数量。
  38. /// </summary>
  39. public int EventHandlerCount
  40. {
  41. get
  42. {
  43. return m_EventHandlers.Count;
  44. }
  45. }
  46. /// <summary>
  47. /// 获取事件数量。
  48. /// </summary>
  49. public int EventCount
  50. {
  51. get
  52. {
  53. return m_Events.Count;
  54. }
  55. }
  56. /// <summary>
  57. /// 事件池轮询。
  58. /// </summary>
  59. /// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
  60. /// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
  61. public void Update(float elapseSeconds, float realElapseSeconds)
  62. {
  63. lock (m_Events)
  64. {
  65. while (m_Events.Count > 0)
  66. {
  67. Event eventNode = m_Events.Dequeue();
  68. HandleEvent(eventNode.Sender, eventNode.EventArgs);
  69. ReferencePool.Release(eventNode);
  70. }
  71. }
  72. }
  73. /// <summary>
  74. /// 关闭并清理事件池。
  75. /// </summary>
  76. public void Shutdown()
  77. {
  78. Clear();
  79. m_EventHandlers.Clear();
  80. m_CachedNodes.Clear();
  81. m_TempNodes.Clear();
  82. m_DefaultHandler = null;
  83. }
  84. /// <summary>
  85. /// 清理事件。
  86. /// </summary>
  87. public void Clear()
  88. {
  89. lock (m_Events)
  90. {
  91. m_Events.Clear();
  92. }
  93. }
  94. /// <summary>
  95. /// 获取事件处理函数的数量。
  96. /// </summary>
  97. /// <param name="id">事件类型编号。</param>
  98. /// <returns>事件处理函数的数量。</returns>
  99. public int Count(int id)
  100. {
  101. GameFrameworkLinkedListRange<EventHandler<T>> range = default(GameFrameworkLinkedListRange<EventHandler<T>>);
  102. if (m_EventHandlers.TryGetValue(id, out range))
  103. {
  104. return range.Count;
  105. }
  106. return 0;
  107. }
  108. /// <summary>
  109. /// 检查是否存在事件处理函数。
  110. /// </summary>
  111. /// <param name="id">事件类型编号。</param>
  112. /// <param name="handler">要检查的事件处理函数。</param>
  113. /// <returns>是否存在事件处理函数。</returns>
  114. public bool Check(int id, EventHandler<T> handler)
  115. {
  116. if (handler == null)
  117. {
  118. throw new GameFrameworkException("Event handler is invalid.");
  119. }
  120. return m_EventHandlers.Contains(id, handler);
  121. }
  122. /// <summary>
  123. /// 订阅事件处理函数。
  124. /// </summary>
  125. /// <param name="id">事件类型编号。</param>
  126. /// <param name="handler">要订阅的事件处理函数。</param>
  127. public void Subscribe(int id, EventHandler<T> handler)
  128. {
  129. if (handler == null)
  130. {
  131. throw new GameFrameworkException("Event handler is invalid.");
  132. }
  133. if (!m_EventHandlers.Contains(id))
  134. {
  135. m_EventHandlers.Add(id, handler);
  136. }
  137. else if ((m_EventPoolMode & EventPoolMode.AllowMultiHandler) != EventPoolMode.AllowMultiHandler)
  138. {
  139. throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow multi handler.", id));
  140. }
  141. else if ((m_EventPoolMode & EventPoolMode.AllowDuplicateHandler) != EventPoolMode.AllowDuplicateHandler && Check(id, handler))
  142. {
  143. throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow duplicate handler.", id));
  144. }
  145. else
  146. {
  147. m_EventHandlers.Add(id, handler);
  148. }
  149. }
  150. /// <summary>
  151. /// 取消订阅事件处理函数。
  152. /// </summary>
  153. /// <param name="id">事件类型编号。</param>
  154. /// <param name="handler">要取消订阅的事件处理函数。</param>
  155. public void Unsubscribe(int id, EventHandler<T> handler)
  156. {
  157. if (handler == null)
  158. {
  159. throw new GameFrameworkException("Event handler is invalid.");
  160. }
  161. if (m_CachedNodes.Count > 0)
  162. {
  163. foreach (KeyValuePair<object, LinkedListNode<EventHandler<T>>> cachedNode in m_CachedNodes)
  164. {
  165. if (cachedNode.Value != null && cachedNode.Value.Value == handler)
  166. {
  167. m_TempNodes.Add(cachedNode.Key, cachedNode.Value.Next);
  168. }
  169. }
  170. if (m_TempNodes.Count > 0)
  171. {
  172. foreach (KeyValuePair<object, LinkedListNode<EventHandler<T>>> cachedNode in m_TempNodes)
  173. {
  174. m_CachedNodes[cachedNode.Key] = cachedNode.Value;
  175. }
  176. m_TempNodes.Clear();
  177. }
  178. }
  179. if (!m_EventHandlers.Remove(id, handler))
  180. {
  181. throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not exists specified handler.", id));
  182. }
  183. }
  184. /// <summary>
  185. /// 设置默认事件处理函数。
  186. /// </summary>
  187. /// <param name="handler">要设置的默认事件处理函数。</param>
  188. public void SetDefaultHandler(EventHandler<T> handler)
  189. {
  190. m_DefaultHandler = handler;
  191. }
  192. /// <summary>
  193. /// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。
  194. /// </summary>
  195. /// <param name="sender">事件源。</param>
  196. /// <param name="e">事件参数。</param>
  197. public void Fire(object sender, T e)
  198. {
  199. if (e == null)
  200. {
  201. throw new GameFrameworkException("Event is invalid.");
  202. }
  203. Event eventNode = Event.Create(sender, e);
  204. lock (m_Events)
  205. {
  206. m_Events.Enqueue(eventNode);
  207. }
  208. }
  209. /// <summary>
  210. /// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。
  211. /// </summary>
  212. /// <param name="sender">事件源。</param>
  213. /// <param name="e">事件参数。</param>
  214. public void FireNow(object sender, T e)
  215. {
  216. if (e == null)
  217. {
  218. throw new GameFrameworkException("Event is invalid.");
  219. }
  220. HandleEvent(sender, e);
  221. }
  222. /// <summary>
  223. /// 处理事件结点。
  224. /// </summary>
  225. /// <param name="sender">事件源。</param>
  226. /// <param name="e">事件参数。</param>
  227. private void HandleEvent(object sender, T e)
  228. {
  229. bool noHandlerException = false;
  230. GameFrameworkLinkedListRange<EventHandler<T>> range = default(GameFrameworkLinkedListRange<EventHandler<T>>);
  231. if (m_EventHandlers.TryGetValue(e.Id, out range))
  232. {
  233. LinkedListNode<EventHandler<T>> current = range.First;
  234. while (current != null && current != range.Terminal)
  235. {
  236. m_CachedNodes[e] = current.Next != range.Terminal ? current.Next : null;
  237. current.Value(sender, e);
  238. current = m_CachedNodes[e];
  239. }
  240. m_CachedNodes.Remove(e);
  241. }
  242. else if (m_DefaultHandler != null)
  243. {
  244. m_DefaultHandler(sender, e);
  245. }
  246. else if ((m_EventPoolMode & EventPoolMode.AllowNoHandler) == 0)
  247. {
  248. noHandlerException = true;
  249. }
  250. ReferencePool.Release(e);
  251. if (noHandlerException)
  252. {
  253. throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow no handler.", e.Id));
  254. }
  255. }
  256. }
  257. }