//------------------------------------------------------------ // Game Framework // Copyright © 2013-2021 loyalsoft. All rights reserved. // Homepage: http://www.game7000.com/ // Feedback: http://www.game7000.com/ //------------------------------------------------------------ using System; using System.Collections.Generic; namespace GameFramework { /// /// 事件池。 /// /// 事件类型。 internal sealed partial class EventPool where T : BaseEventArgs { private readonly GameFrameworkMultiDictionary> m_EventHandlers; private readonly Queue m_Events; private readonly Dictionary>> m_CachedNodes; private readonly Dictionary>> m_TempNodes; private readonly EventPoolMode m_EventPoolMode; private EventHandler m_DefaultHandler; /// /// 初始化事件池的新实例。 /// /// 事件池模式。 public EventPool(EventPoolMode mode) { m_EventHandlers = new GameFrameworkMultiDictionary>(); m_Events = new Queue(); m_CachedNodes = new Dictionary>>(); m_TempNodes = new Dictionary>>(); m_EventPoolMode = mode; m_DefaultHandler = null; } /// /// 获取事件处理函数的数量。 /// public int EventHandlerCount { get { return m_EventHandlers.Count; } } /// /// 获取事件数量。 /// public int EventCount { get { return m_Events.Count; } } /// /// 事件池轮询。 /// /// 逻辑流逝时间,以秒为单位。 /// 真实流逝时间,以秒为单位。 public void Update(float elapseSeconds, float realElapseSeconds) { lock (m_Events) { while (m_Events.Count > 0) { Event eventNode = m_Events.Dequeue(); HandleEvent(eventNode.Sender, eventNode.EventArgs); ReferencePool.Release(eventNode); } } } /// /// 关闭并清理事件池。 /// public void Shutdown() { Clear(); m_EventHandlers.Clear(); m_CachedNodes.Clear(); m_TempNodes.Clear(); m_DefaultHandler = null; } /// /// 清理事件。 /// public void Clear() { lock (m_Events) { m_Events.Clear(); } } /// /// 获取事件处理函数的数量。 /// /// 事件类型编号。 /// 事件处理函数的数量。 public int Count(int id) { GameFrameworkLinkedListRange> range = default(GameFrameworkLinkedListRange>); if (m_EventHandlers.TryGetValue(id, out range)) { return range.Count; } return 0; } /// /// 检查是否存在事件处理函数。 /// /// 事件类型编号。 /// 要检查的事件处理函数。 /// 是否存在事件处理函数。 public bool Check(int id, EventHandler handler) { if (handler == null) { throw new GameFrameworkException("Event handler is invalid."); } return m_EventHandlers.Contains(id, handler); } /// /// 订阅事件处理函数。 /// /// 事件类型编号。 /// 要订阅的事件处理函数。 public void Subscribe(int id, EventHandler handler) { if (handler == null) { throw new GameFrameworkException("Event handler is invalid."); } if (!m_EventHandlers.Contains(id)) { m_EventHandlers.Add(id, handler); } else if ((m_EventPoolMode & EventPoolMode.AllowMultiHandler) != EventPoolMode.AllowMultiHandler) { throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow multi handler.", id)); } else if ((m_EventPoolMode & EventPoolMode.AllowDuplicateHandler) != EventPoolMode.AllowDuplicateHandler && Check(id, handler)) { throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow duplicate handler.", id)); } else { m_EventHandlers.Add(id, handler); } } /// /// 取消订阅事件处理函数。 /// /// 事件类型编号。 /// 要取消订阅的事件处理函数。 public void Unsubscribe(int id, EventHandler handler) { if (handler == null) { throw new GameFrameworkException("Event handler is invalid."); } if (m_CachedNodes.Count > 0) { foreach (KeyValuePair>> cachedNode in m_CachedNodes) { if (cachedNode.Value != null && cachedNode.Value.Value == handler) { m_TempNodes.Add(cachedNode.Key, cachedNode.Value.Next); } } if (m_TempNodes.Count > 0) { foreach (KeyValuePair>> cachedNode in m_TempNodes) { m_CachedNodes[cachedNode.Key] = cachedNode.Value; } m_TempNodes.Clear(); } } if (!m_EventHandlers.Remove(id, handler)) { throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not exists specified handler.", id)); } } /// /// 设置默认事件处理函数。 /// /// 要设置的默认事件处理函数。 public void SetDefaultHandler(EventHandler handler) { m_DefaultHandler = handler; } /// /// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。 /// /// 事件源。 /// 事件参数。 public void Fire(object sender, T e) { if (e == null) { throw new GameFrameworkException("Event is invalid."); } Event eventNode = Event.Create(sender, e); lock (m_Events) { m_Events.Enqueue(eventNode); } } /// /// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。 /// /// 事件源。 /// 事件参数。 public void FireNow(object sender, T e) { if (e == null) { throw new GameFrameworkException("Event is invalid."); } HandleEvent(sender, e); } /// /// 处理事件结点。 /// /// 事件源。 /// 事件参数。 private void HandleEvent(object sender, T e) { bool noHandlerException = false; GameFrameworkLinkedListRange> range = default(GameFrameworkLinkedListRange>); if (m_EventHandlers.TryGetValue(e.Id, out range)) { LinkedListNode> current = range.First; while (current != null && current != range.Terminal) { m_CachedNodes[e] = current.Next != range.Terminal ? current.Next : null; current.Value(sender, e); current = m_CachedNodes[e]; } m_CachedNodes.Remove(e); } else if (m_DefaultHandler != null) { m_DefaultHandler(sender, e); } else if ((m_EventPoolMode & EventPoolMode.AllowNoHandler) == 0) { noHandlerException = true; } ReferencePool.Release(e); if (noHandlerException) { throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow no handler.", e.Id)); } } } }