/// <summary> /// Adds a listener to this Signal. /// </summary> /// <param name="listener">The Delegate to call when this Signal is dispatched.</param> /// <param name="priority">The priority of this Slot. Slots are called lowest-to-highest priority.</param> /// <param name="isOnce">Determines if this listener is called only once or indefinitely on Dispatch().</param> /// <returns></returns> protected SlotBase Add(Delegate listener, int priority, bool isOnce) { if (listener == null) { return(null); } SlotBase slot = Get(listener); if (!slot) { if (slotsPooled.Count > 0) { slot = slotsPooled.Pop(); } else { slot = CreateSlot(); } } slot.Listener = listener; slot.Priority = priority; slot.IsOnce = isOnce; slot.Signal = this; PriorityChanged(slot, slot.Priority, 0); isDisposed = false; return(slot); }
/// <summary> /// Calls Dispose() on a Slot and pools it for reuse. This is done at the end of /// a Dispatch() or when a Slot is removed and no dispatches are occurring. /// </summary> /// <param name="slot"></param> private void DisposeSlot(SlotBase slot) { slot.Dispose(); if (!isDisposed) { slotsPooled.Push(slot); } }
/// <summary> /// Internal method that is called from Slots when their priority has changed. /// Keeps the Signal's Slot order up to date. Should NOT be called from anywhere else! /// </summary> /// <param name="slot"></param> /// <param name="current"></param> /// <param name="previous"></param> internal void PriorityChanged(SlotBase slot, int current, int previous) { slots.Remove(slot); for (int index = slots.Count; index > 0; --index) { if (slots[index - 1].Priority <= slot.Priority) { slots.Insert(index, slot); return; } } slots.Insert(0, slot); }
/// <summary> /// Removes the listener from this Signal at the given index. /// </summary> /// <param name="index">The index of the Slot to remove. Slots are ordered by priority.</param> /// <returns></returns> public bool RemoveAt(int index) { if (index < 0) { return(false); } if (index >= slots.Count) { return(false); } SlotBase slot = slots[index]; slots.RemoveAt(index); if (dispatching > 0) { slotsRemoved.Push(slot); } else { DisposeSlot(slot); } return(true); }