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