/* ---------------------------------------------------------------------------------------- */ protected void ListAdd(SignalConnectionBase conn, bool prioritize) { if (prioritize) { // Prepend it to the beginning of the list conn._next = _head; _head = conn; } else { // Append it to the end of the list SignalConnectionBase tail = null, p = _head; while (p != null) { tail = p; p = p._next; } if (tail != null) { tail._next = conn; } else { _head = conn; } } }
/* ---------------------------------------------------------------------------------------- */ protected void DidEmit(SignalConnectionBase head) { _head = head; Task snapshot = _deferredTasks; _deferredTasks = null; while (snapshot != null) { snapshot.fn(); snapshot = snapshot.next; } }
/* ---------------------------------------------------------------------------------------- */ protected SignalConnectionBase WillEmit() { // Should never happen, since the public emit methods will defer, but just in case... if (Dispatching()) { throw new Exception(); } SignalConnectionBase snapshot = _head; _head = DISPATCHING_SENTINEL; return(snapshot); }
/* ---------------------------------------------------------------------------------------- */ public void Disconnect(SignalConnectionBase conn) { if (Dispatching()) { Defer(delegate() { ListRemove(conn); }); } else { ListRemove(conn); } }
/* ---------------------------------------------------------------------------------------- */ protected SignalConnection ConnectImpl(Action listener, bool prioritize) { SignalConnectionBase conn = new SignalConnectionBase(this, listener); if (Dispatching()) { Defer(delegate() { ListAdd(conn, prioritize); }); } else { ListAdd(conn, prioritize); } return(conn); }
/* ---------------------------------------------------------------------------------------- */ private void EmitImpl() { SignalConnectionBase head = WillEmit(); SignalConnectionBase p = head; while (p != null) { p._listener(); if (!p.stayInList) { p.Dispose(); } p = p._next; } DidEmit(head); }
/* ---------------------------------------------------------------------------------------- */ protected void ListRemove(SignalConnectionBase conn) { SignalConnectionBase prev = null, p = _head; while (p != null) { if (p == conn) { // Splice out p var next = p._next; if (prev == null) { _head = next; } else { prev._next = next; } return; } prev = p; p = p._next; } }
/* ---------------------------------------------------------------------------------------- */ public Signal(Action listener = null) { _head = (listener != null) ? new SignalConnectionBase(this, listener) : null; _deferredTasks = null; }