1 module util.signals;
2 
3 /**
4  * Signals and Slots are an implementation of the Observer Pattern.
5  * Essentially, when a Signal is emitted, a list of connected Observers
6  * (called slots) are called.
7  *
8  * There have been several D implementations of Signals and Slots.
9  * This version makes use of several new features in D, which make
10  * using it simpler and less error prone. In particular, it is no
11  * longer necessary to instrument the slots.
12  *
13  * References:
14  *      $(LINK2 http://scottcollins.net/articles/a-deeper-look-at-_signals-and-slots.html, A Deeper Look at Signals and Slots)$(BR)
15  *      $(LINK2 http://en.wikipedia.org/wiki/Observer_pattern, Observer pattern)$(BR)
16  *      $(LINK2 http://en.wikipedia.org/wiki/Signals_and_slots, Wikipedia)$(BR)
17  *      $(LINK2 http://boost.org/doc/html/$(SIGNALS).html, Boost Signals)$(BR)
18  *      $(LINK2 http://doc.trolltech.com/4.1/signalsandslots.html, Qt)$(BR)
19  *
20  *      There has been a great deal of discussion in the D newsgroups
21  *      over this, and several implementations:
22  *
23  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/announce/signal_slots_library_4825.html, signal slots library)$(BR)
24  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/Signals_and_Slots_in_D_42387.html, Signals and Slots in D)$(BR)
25  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/Dynamic_binding_--_Qt_s_Signals_and_Slots_vs_Objective-C_42260.html, Dynamic binding -- Qt's Signals and Slots vs Objective-C)$(BR)
26  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/Dissecting_the_SS_42377.html, Dissecting the SS)$(BR)
27  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/dwt/about_harmonia_454.html, about harmonia)$(BR)
28  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/announce/1502.html, Another event handling module)$(BR)
29  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/41825.html, Suggestion: signal/slot mechanism)$(BR)
30  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/13251.html, Signals and slots?)$(BR)
31  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/10714.html, Signals and slots ready for evaluation)$(BR)
32  *      $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/1393.html, Signals & Slots for Walter)$(BR)
33  *      $(LINK2 http://www.digitalmars.com/d/archives/28456.html, Signal/Slot mechanism?)$(BR)
34  *      $(LINK2 http://www.digitalmars.com/d/archives/19470.html, Modern Features?)$(BR)
35  *      $(LINK2 http://www.digitalmars.com/d/archives/16592.html, Delegates vs interfaces)$(BR)
36  *      $(LINK2 http://www.digitalmars.com/d/archives/16583.html, The importance of component programming (properties, signals and slots, etc))$(BR)
37  *      $(LINK2 http://www.digitalmars.com/d/archives/16368.html, signals and slots)$(BR)
38  *
39  * Bugs:
40  *      Not safe for multiple threads operating on the same signals
41  *      or slots.
42  * 
43  *      Safety of handlers is not yet enforced
44  * Macros:
45  *      WIKI = Phobos/StdSignals
46  *      SIGNALS=signals
47  *
48  * Copyright: Copyright Digital Mars 2000 - 2009.
49  * License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
50  * Authors:   $(WEB digitalmars.com, Walter Bright), 
51  *            Johannes Pfau
52  */
53 /*          Copyright Digital Mars 2000 - 2009.
54  * Distributed under the Boost Software License, Version 1.0.
55  *    (See accompanying file LICENSE_1_0.txt or copy at
56  *          http://www.boost.org/LICENSE_1_0.txt)
57  */
58 //~ module signals;
59 
60 import std.algorithm; //find
61 import std.container; //SList
62 import std.functional; //toDelegate
63 import std.range; //take
64 import std.traits; //isPointer, isSafe
65 
66 //Bug 4536
67 private template Init(T...)
68 {
69     T Init;
70 }
71 
72 template isHandlerDelegate(T, Types...)
73 {
74     static if(is(T == delegate))
75     {
76         enum bool isHandlerDelegate = (is(typeof(T.init(Init!(Types))))
77                             && (is(ReturnType!(T) == void)
78                             || is(ReturnType!(T) == bool)));
79     }
80     else
81     {
82         enum bool isHandlerDelegate = false;
83     }
84 }
85 
86 template isHandlerFunction(T, Types...)
87 {
88     static if(isPointer!(T))
89     {
90         enum bool isHandlerFunction = (isPointer!(T) && is(pointerTarget!(T) == function)
91                             && is(typeof(T.init(Init!(Types))))
92                             && (is(ReturnType!(T) == void)
93                             || is(ReturnType!(T) == bool)));
94     }
95     else
96     {
97         enum bool isHandlerFunction = false;
98     }
99 }
100 
101 template isHandlerStruct(T, Types...)
102 {
103     static if(isPointer!(T))
104     {
105         enum bool isHandlerStruct = (is(pointerTarget!(T) == struct)
106                         //&& (isSafe!(pointerTarget!(T).init))
107                         && is(typeof(pointerTarget!(T).init.opCall(Init!(Types))))
108                         && (is(ReturnType!(T) == void)
109                         || is(ReturnType!(T) == bool))); 
110     }
111     else
112     {
113         enum bool isHandlerStruct = false;
114     }
115 }
116 
117 unittest
118 {
119     struct tmp
120     {
121         @safe bool opCall() {return false;}
122     }
123     tmp* a = new tmp();
124     
125     assert(isHandlerStruct!(typeof(a)));
126     tmp b;
127     assert(!isHandlerStruct!(typeof(b)));
128 }
129 
130 //Checking for unsafe handlers is not yet implemented
131 /*
132 unittest
133 {
134     struct tmp
135     {
136         bool opCall() {return false;}
137     }
138     tmp* a = new tmp();
139     
140     assert(!isHandlerStruct!(typeof(a)));
141     tmp b;
142     assert(!isHandlerStruct!(typeof(b)));
143 }
144 */
145 
146 template isHandlerClass(T, Types...)
147 {
148     enum bool isHandlerClass = (is(T == class)
149                         && is(typeof(T.init.opCall(Init!(Types))))
150                         && (is(ReturnType!(T) == void)
151                         || is(ReturnType!(T) == bool)));
152 }
153 
154 template isHandler(T, Types...)
155 {
156     enum bool isHandler = isHandlerDelegate!(T, Types) || isHandlerFunction!(T, Types)
157         || isHandlerClass!(T, Types) || isHandlerStruct!(T, Types);
158 }
159 
160 unittest
161 {
162     struct tmp
163     {
164         @safe void opCall(){}
165     }
166     struct tmp2
167     {
168         @safe char opCall(){ return 'c';}
169     }
170     struct tmp3
171     {
172         @safe bool opCall(){ return true;}
173     }
174     tmp* a = new tmp();
175 
176     assert(isHandler!(typeof(a)));
177     assert(!isHandler!(typeof(a), int));
178     assert(!isHandler!(typeof(a), int, bool));
179     assert(!isHandler!(typeof(a), int, bool, string));
180 
181     tmp b;
182     assert(!isHandler!(typeof(b)));
183     assert(!isHandler!(typeof(b), int));
184     assert(!isHandler!(typeof(b), int, bool));
185     assert(!isHandler!(typeof(b), int, bool, string));
186 
187     tmp2 c;
188     assert(!isHandler!(typeof(c)));
189     assert(!isHandler!(typeof(c), int));
190     assert(!isHandler!(typeof(c), int, bool));
191     assert(!isHandler!(typeof(c), int, bool, string));
192 
193     tmp3* d = new tmp3();
194     assert(isHandler!(typeof(d)));
195     assert(!isHandler!(typeof(d), int));
196     assert(!isHandler!(typeof(d), int, bool));
197     assert(!isHandler!(typeof(d), int, bool, string));
198 }
199 
200 unittest
201 {
202     class tmp
203     {
204         @safe void opCall(int i){}
205     }
206     class tmp2
207     {
208         @safe char opCall(string a, bool b){ return 'c';}
209     }
210     class tmp3
211     {
212         @safe bool opCall(char b){ return true;}
213     }
214     tmp a = new tmp();
215 
216     assert(!isHandler!(typeof(a)));
217     assert(isHandler!(typeof(a), int));
218     assert(!isHandler!(typeof(a), int, bool));
219     assert(!isHandler!(typeof(a), int, bool, string));
220 
221     tmp2 b = new tmp2();
222     assert(!isHandler!(typeof(b)));
223     assert(!isHandler!(typeof(b), string, bool));
224     assert(!isHandler!(typeof(b), int, bool));
225     assert(!isHandler!(typeof(b), int, bool, string));
226 
227     tmp3 c = new tmp3();
228     assert(!isHandler!(typeof(c)));
229     assert(isHandler!(typeof(c), char));
230     assert(!isHandler!(typeof(c), int, bool));
231     assert(!isHandler!(typeof(c), int, bool, string));
232 }
233 
234 unittest
235 {
236     static @safe void test(int a, int b) {};
237     static @safe void test2(int b) {};
238     static @safe bool test3(int a, int b) {return true;};
239     static @safe bool test4(int b) {return true;};
240     assert(isHandler!(typeof(&test), int, int));
241     assert(!isHandler!(typeof(&test)));
242     assert(isHandler!(typeof(&test2), int));
243     assert(!isHandler!(typeof(&test2, string)));
244     assert(isHandler!(typeof(&test3), int, int));
245     assert(!isHandler!(typeof(&test3), bool));
246     assert(isHandler!(typeof(&test4), int));
247     assert(!isHandler!(typeof(&test4)));
248 }
249 
250 unittest
251 {
252     @safe void test(int a, int b) {};
253     @safe void test2(int b) {};
254     @safe bool test3(int a, int b) {return true;};
255     @safe bool test4(int b) {return true;};
256 
257     assert(isHandler!(typeof(&test), int, int));
258     assert(!isHandler!(typeof(&test)));
259     assert(isHandler!(typeof(&test2), int));
260     assert(!isHandler!(typeof(&test2, string)));
261     assert(isHandler!(typeof(&test3), int, int));
262     assert(!isHandler!(typeof(&test3), bool));
263     assert(isHandler!(typeof(&test4), int));
264     assert(!isHandler!(typeof(&test4)));
265 }
266 
267 /**
268  * This Signal struct is an implementation of the Observer pattern.
269  *
270  * All D callable types (functions, delegates, structs with opCall,
271  * classes with opCall) can be registered with a signal. When the signal
272  * occurs all assigned callables are called.
273  *
274  * Structs with opCall are only supported if they're passed by pointer. These
275  * structs are then expected to be allocated on the heap.
276  *
277  * Delegates to struct instances or nested functions are supported. You
278  * have to make sure to disconnect these delegates from the Signal before
279  * they go out of scope though.
280  *
281  * The return type of the handlers must be void or bool. If the return
282  * type is bool and the handler returns false the remaining handlers are
283  * not called. If true is returned or the type is void the remaining
284  * handlers are called.
285  * 
286  * SafeD:
287  * This Signal template can be used in safeD; all public functions
288  * are @safe or @trusted. All handlers connected to
289  * a signal must be @safe or @trusted. It's currently not possible to
290  * enforce the safety of the handlers, but it will be enforced as soon
291  * as possible.
292  * 
293  * Examples:
294  * -------------------------------------------------------------------
295  * import std.stdio;
296  * import std.signals;
297  *
298  * //same for classes
299  * struct A
300  * {
301  *     string payload;
302  *     @safe bool opCall(float f, string s)
303  *     {
304  *         writefln("A: %f:%s:%s", f, s, payload);
305  *         return true;
306  *     }
307  * }
308  * 
309  * @safe void testFunc(float f, string s)
310  * {
311  *      writefln("Function: %f:%s", f, s);
312  * }
313  *
314  * Signal!(float, string) onTest;
315  *
316  * void main()
317  * {
318  *     A* a = new A();
319  *     a.payload = "test payload";
320  *     onTest.connect(a);
321  *     onTest ~= &testFunc;
322  *     onTest(0.123f, "first call");
323  * }
324  * -------------------------------------------------------------------
325  */
326 public struct Signal(Types...)
327 {
328     private:
329         //A slot is implemented as a delegate. The slot_t is the type of the delegate.
330         alias bool delegate(Types) slot_t;
331         //Same as slot_t but with void return type
332         alias void delegate(Types) void_slot_t;
333 
334         /* This struct stores one delegate and information whether the
335          * delegate returns a bool or void */
336         static struct Callable
337         {
338             //The void_slot_t delegate
339             slot_t deleg;
340             bool returnsBool = true;
341 
342             this(void_slot_t del)
343             {
344                 this.deleg = cast(slot_t)del;
345                 this.returnsBool = false;
346             }
347             this(slot_t del)
348             {
349                 this.deleg = del;
350             }
351         }
352         
353         SList!(Callable) handlers;
354 
355         /*
356          * Get a Callable for the handler.
357          * Handler can be a void function, void delegate, bool
358          * function, bool delegate, class with opCall or a pointer to
359          * a struct with opCall.
360          */
361         @trusted Callable getCallable(T)(T handler) if(isHandler!(T, Types))
362         {
363             static if(isHandlerDelegate!(T, Types) && is(ReturnType!(T) == void))
364             {
365                 return Callable(cast(void_slot_t)handler);
366             }
367             else static if(isHandlerFunction!(T, Types) && is(ReturnType!(T) == void))
368             {
369                 void delegate(Types) call = toDelegate(cast(void function(Types))handler);
370                 return Callable(call);
371             }
372             else static if(isHandlerDelegate!(T, Types) && is(ReturnType!(T) == bool))
373             {
374                 return Callable(cast(slot_t)handler);
375             }
376             else static if(isHandlerFunction!(T, Types) && is(ReturnType!(T) == bool))
377             {
378                 return Callable(toDelegate(cast(bool function(Types))handler));
379             }
380             else static if(isHandlerStruct!(T, Types))
381             {
382                 static if(is(ReturnType!(T) == void))
383                 {
384                     return Callable(cast(void_slot_t)&handler.opCall);
385                 }
386                 else static if(is(ReturnType!(T) == bool))
387                 {
388                     return Callable(cast(slot_t)&handler.opCall);
389                 }
390                 else
391                 {
392                     static assert(false, "BUG: Internal error");
393                 }
394             }
395             else static if(isHandlerClass!(T, Types))
396             {
397                 static if(is(ReturnType!(T) == void))
398                 {
399                     return Callable(cast(void_slot_t)&handler.opCall);
400                 }
401                 else static if(is(ReturnType!(T) == bool))
402                 {
403                     return Callable(cast(slot_t)&handler.opCall);
404                 }
405                 else
406                 {
407                     static assert(false, "BUG: Internal error");
408                 }
409             }
410             else
411             {
412                 static assert(false, "BUG: Input type not supported. "
413                     "Please file a bug report.");
414             }
415         }
416 
417     public:
418         /**
419          * Set to false to disable signal emission
420          * 
421          * Examples:
422          * --------------------------------
423          * bool called = false;
424          * @safe void handler() { called = true; }
425          * Signal!() onTest;
426          * onTest ~= &handler;
427          * onTest();
428          * assert(called);
429          * called = false;
430          * onTest.enabled = false;
431          * onTest();
432          * assert(!called);
433          * onTest.enabled = true;
434          * onTest();
435          * assert(called);
436          * --------------------------------
437          */
438         @safe bool enabled = true;
439 
440         /**
441          * Check whether a handler is already connected
442          * 
443          * Examples:
444          * --------------------------------
445          * @safe void handler() {};
446          * Signal!() onTest;
447          * assert(!onTest.isConnected(&handler));
448          * onTest ~= &handler;
449          * assert(onTest.isConnected(&handler));
450          * onTest();
451          * --------------------------------
452          */
453         @trusted bool isConnected(T)(T handler) if(isHandler!(T, Types))
454         {
455             Callable call = getCallable(handler);
456             return !find(handlers[], call).empty;
457         }
458 
459         /**
460          * Add a handler to the list of handlers to be called when emit() is called.
461          * The handler is added at the end of the list.
462          * 
463          * Throws:
464          * Exception if handler is already registered
465          * (Only if asserts are enabled! Does not throw
466          * in release mode!)
467          * 
468          * Returns:
469          * The handler that was passed in as a paramter
470          * 
471          * Examples:
472          * --------------------------------
473          * int val;
474          * string text;
475          * @safe void handler(int i, string t)
476          * {
477          *     val = i;
478          *     text = t;
479          * }
480          * 
481          * Signal!(int, string) onTest;
482          * onTest.connect(&handler);
483          * onTest(1, "test");
484          * assert(val == 1);
485          * assert(text == "test");
486          * --------------------------------
487          */
488         @trusted T connect(T)(T handler) if(isHandler!(T, Types))
489         {
490             Callable call = getCallable(handler);
491             assert(find(handlers[], call).empty, "Handler is already registered!");
492             handlers.stableInsertAfter(handlers[], call);
493             return handler;
494         }
495 
496         /**
497          * Add a handler to the list of handlers to be called when emit() is called.
498          * Add this handler at the top of the list, so it will be called before all
499          * other handlers.
500          * 
501          * Throws:
502          * Exception if handler is already registered
503          * (Only if asserts are enabled! Does not throw
504          * in release mode!)
505          * 
506          * Returns:
507          * The handler that was passed in as a paramter
508          * 
509          * --------------------------------
510          * bool firstCalled, secondCalled;
511          * @safe void handler1() {firstCalled = true;}
512          * @safe void handler2()
513          * {
514          *     secondCalled = true;
515          *     assert(firstCalled);
516          * }
517          * Signal!() onTest;
518          * onTest ~= &handler2;
519          * onTest.connectFirst(&handler1);
520          * onTest();
521          * assert(firstCalled && secondCalled);
522          * --------------------------------
523          */
524         @trusted T connectFirst(T)(T handler) if(isHandler!(T, Types))
525         {
526             Callable call = getCallable(handler);
527             assert(find(handlers[], call).empty, "Handler is already registered!");
528             handlers.stableInsertFront(call);
529             return handler;
530         }
531 
532         /**
533          * Add a handler to be called after another handler.
534          * Params:
535          *     afterThis = The new attached handler will be called after this handler
536          *     handler = The handler to be attached
537          * 
538          * Throws:
539          * Exception if handler is already registered
540          * (Only if asserts are enabled! Does not throw
541          * in release mode!)
542          * 
543          * Exception if afterThis is not registered
544          * (Always, even if asserts are disabled)
545          * 
546          * Returns:
547          * The handler that has been connected
548          * 
549          * Examples:
550          * --------------------------------
551          * bool firstCalled, secondCalled, thirdCalled;
552          * @safe void handler1() {firstCalled = true;}
553          * @safe void handler2()
554          * {
555          *     secondCalled = true;
556          *     assert(firstCalled);
557          *     assert(thirdCalled);
558          * }
559          * @safe void handler3()
560          * {
561          *     thirdCalled = true;
562          *     assert(firstCalled);
563          *     assert(!secondCalled);
564          * }
565          * Signal!() onTest;
566          * onTest ~= &handler1;
567          * onTest ~= &handler2;
568          * auto h = onTest.connectAfter(&handler1, &handler3);
569          * assert(h == &handler3);
570          * onTest();
571          * assert(firstCalled && secondCalled && thirdCalled);
572          * --------------------------------
573          */
574         @trusted T connectAfter(T, U)(T afterThis, U handler)
575             if(isHandler!(T, Types) && isHandler!(U, Types))
576         {
577             Callable after = getCallable(afterThis);
578             Callable call = getCallable(handler);
579             auto location = find(handlers[], after);
580             if(location.empty)
581             {
582                  throw new Exception("Handler 'afterThis' is not registered!");
583             }
584             assert(find(handlers[], call).empty, "Handler is already registered!");
585             handlers.stableInsertAfter(take(location, 1), call);
586             return handler;
587         }
588 
589         /**
590          * Add a handler to be called before another handler.
591          * Params:
592          *     beforeThis = The new attached handler will be called after this handler
593          *     handler = The handler to be attached
594          * 
595          * Throws:
596          * Exception if handler is already registered
597          * (Only if asserts are enabled! Does not throw
598          * in release mode!)
599          * 
600          * Returns:
601          * The handler that has been connected
602          * 
603          * Exception if beforeThis is not registered
604          * (Always, even if asserts are disabled)
605          * 
606          * Examples:
607          * --------------------------------
608          * bool firstCalled, secondCalled, thirdCalled;
609          * @safe void handler1() {firstCalled = true;}
610          * @safe void handler2()
611          * {
612          *     secondCalled = true;
613          *     assert(firstCalled);
614          *     assert(!thirdCalled);
615          * }
616          * @safe void handler3()
617          * {
618          *     thirdCalled = true;
619          *     assert(firstCalled);
620          *     assert(secondCalled);
621          * }
622          * Signal!() onTest;
623          * onTest ~= &handler1;
624          * onTest ~= &handler3;
625          * onTest.connectBefore(&handler3, &handler2);
626          * onTest();
627          * assert(firstCalled && secondCalled && thirdCalled);
628          * --------------------------------
629          */
630         @trusted T connectBefore(T, U)(T beforeThis, U handler)
631             if(isHandler!(T, Types) && isHandler!(U, Types))
632         {
633             Callable before = getCallable(beforeThis);
634             Callable call = getCallable(handler);
635             auto location = find(handlers[], before);
636             if(location.empty)
637             {
638                  throw new Exception("Handler 'beforeThis' is not registered!");
639             }
640             assert(find(handlers[], call).empty, "Handler is already registered!");
641             //not exactly fast
642             uint length = walkLength(handlers[]);
643             uint pos = walkLength(location);
644             uint new_location = length - pos;
645             location = handlers[];
646             if(new_location == 0)
647                 handlers.stableInsertFront(call);
648             else
649                 handlers.stableInsertAfter(take(location, new_location), call);
650             return handler;
651         }
652 
653         /**
654          * Remove a handler from the list of handlers to be called when emit() is called.
655          * 
656          * Throws:
657          * Exception if handler is not registered
658          * (Always, even if asserts are disabled)
659          * 
660          * Returns:
661          * The handler that has been disconnected
662          * 
663          * Examples:
664          * --------------------------------
665          * @safe void handler() {};
666          * Signal!() onTest;
667          * onTest.connect(&handler);
668          * onTest.disconnect(&handler);
669          * onTest.connect(&handler);
670          * onTest();
671          * --------------------------------
672          */
673         @trusted T disconnect(T)(T handler) if(isHandler!(T, Types))
674         {
675             Callable call = getCallable(handler);
676             auto pos = find(handlers[], call);
677             if(pos.empty)
678             {
679                 throw new Exception("Handler is not connected");
680             }
681             handlers.stableLinearRemove(take(pos, 1));
682             return handler;
683         }
684 
685         /**
686          * Remove all handlers from the signal
687          * 
688          * Examples:
689          * --------------------------------
690          * @safe void handler() {};
691          * Signal!() onTest;
692          * assert(onTest.calculateLength() == 0);
693          * onTest.connect(&handler);
694          * assert(onTest.calculateLength() == 1);
695          * onTest.clear();
696          * assert(onTest.calculateLength() == 0);
697          * onTest();
698          * --------------------------------
699          */
700         @trusted void clear()
701         {
702             handlers.clear();
703         }
704 
705         /**
706          * Calculate the number of registered handlers
707          *
708          * Complexity: $(BIGOH n)
709          * 
710          * Examples:
711          * --------------------------------
712          * @safe void handler() {};
713          * @safe void handler2() {};
714          * Signal!() onTest;
715          * assert(onTest.calculateLength() == 0);
716          * onTest.connect(&handler);
717          * assert(onTest.calculateLength() == 1);
718          * onTest.connect(&handler2);
719          * assert(onTest.calculateLength() == 2);
720          * onTest.clear();
721          * assert(onTest.calculateLength() == 0);
722          * onTest();
723          * --------------------------------
724          */
725         @trusted uint calculateLength()
726         {
727             return walkLength(handlers[]);
728         }
729 
730         /**
731          * Just like Signal.connect()
732          */
733         @safe T opOpAssign(string op, T)(T rhs) if(op == "~" && isHandler!(T, Types))
734         {
735             return connect!(T)(rhs);
736         }
737 
738         /**
739          * Call the connected handlers as explained in the documentation
740          * for the signal struct.
741          * 
742          * Throws:
743          * Exceptions thrown in the signal handlers
744          * 
745          * Examples:
746          * --------------------------------
747          * @safe void handler() {};
748          * Signal!() onTest;
749          * onTest.connect(&handler);
750          * onTest.emit();
751          * --------------------------------
752          */
753         @trusted void emit(Types params)
754         {
755             if(this.enabled)
756             {
757                 foreach(callable; handlers[])
758                 {
759                     if(callable.returnsBool)
760                     {
761                         slot_t del = cast(slot_t)callable.deleg;
762                         if(!del(params))
763                             return;
764                     }
765                     else
766                     {
767                         void_slot_t del = cast(void_slot_t)callable.deleg;
768                         del(params);
769                     }
770                 }
771             }
772         }
773 
774         /**
775          * Just like emit()
776          */
777         @trusted void opCall(Types params)
778         {
779             emit(params);
780         }
781 }
782 
783 //unit tests
784 unittest
785 {
786     int val;
787     string text;
788     @safe void handler(int i, string t)
789     {
790         val = i;
791         text = t;
792     }
793     @safe static void handler2(int i, string t)
794     {
795     }
796 
797     Signal!(int, string) onTest;
798     onTest.connect(&handler);
799     onTest.connect(&handler2);
800     onTest(1, "test");
801     assert(val == 1);
802     assert(text == "test");
803     onTest(99, "te");
804     assert(val == 99);
805     assert(text == "te");
806 }
807 
808 unittest
809 {
810     @safe void handler() {}
811     Signal!() onTest;
812     onTest.connect(&handler);
813     bool thrown = false;
814     try
815         onTest.connect(&handler);
816     catch(Throwable)
817         thrown = true;
818 
819     assert(thrown);
820 }
821 
822 unittest
823 {
824     @safe void handler() {};
825     Signal!() onTest;
826     onTest.connect(&handler);
827     onTest.disconnect(&handler);
828     onTest.connect(&handler);
829     onTest();
830 }
831 
832 unittest
833 {
834     bool called = false;
835     @safe void handler() { called = true; };
836     Signal!() onTest;
837     onTest ~= &handler;
838     onTest.disconnect(&handler);
839     onTest ~= &handler;
840     onTest();
841     assert(called);
842 }
843 
844 unittest
845 {
846     class handler
847     {
848         @safe void opCall(int i) {}
849     }
850     
851     struct handler2
852     {
853         @safe void opCall(int i) {}
854     }
855     Signal!(int) onTest;
856     onTest ~= new handler;
857     auto h = onTest ~= new handler2;
858     onTest(0);
859     onTest.disconnect(h);
860 }
861 
862 unittest
863 {
864     __gshared bool called = false;
865 
866     struct A
867     {
868         string payload;
869 
870         @trusted void opCall(float f, string s)
871         {
872             assert(payload == "payload");
873             assert(f == 0.1234f);
874             assert(s == "test call");
875             called = true;
876         }
877     }
878 
879     A* a = new A();
880     a.payload = "payload";
881 
882     Signal!(float, string) onTest;
883     onTest.connect(a);
884     onTest(0.1234f, "test call");
885     assert(called);
886 }
887 
888 unittest
889 {
890     __gshared bool called;
891     struct A
892     {
893         string payload;
894         @trusted void opCall(float f, string s)
895         {
896             assert(payload == "payload 2");
897             called = true;
898         }
899     }
900 
901     A* a = new A();
902     a.payload = "payload";
903 
904     Signal!(float, string) onTest;
905     onTest.connect(a);
906     A* b = new A();
907     b.payload = "payload 2";
908     onTest.connect(b);
909     onTest.disconnect(a);
910     onTest(0.1234f, "test call");
911     assert(called);
912 }
913 
914 unittest
915 {
916     struct A
917     {
918         @safe void opCall() {}
919     }
920     A* a = new A();
921 
922     Signal!() onTest;
923     onTest.connect(a);
924     bool thrown = false;
925     try
926         onTest.connect(a);
927     catch(Throwable)
928         thrown = true;
929 
930     assert(thrown);
931 }
932 
933 unittest
934 {
935     struct A
936     {
937         @safe void opCall() {}
938     }
939     A* a = new A();
940 
941     Signal!() onTest;
942     onTest.connect(a);
943     onTest.disconnect(a);
944     bool thrown = false;
945     try
946         onTest.disconnect(a);
947     catch(Throwable)
948         thrown = true;
949 
950     assert(thrown);
951 }
952 
953 unittest
954 {
955     struct A
956     {
957         @safe void opCall() {}
958     }
959     A* a = new A();
960 
961     Signal!() onTest;
962     bool thrown = false;
963     try
964         onTest.disconnect(a);
965     catch(Throwable)
966         thrown = true;
967 
968     assert(thrown);
969 }
970 
971 unittest
972 {
973     bool secondCalled = false;
974     @safe bool first(int i) {return false;}
975     @safe void second(int i) {secondCalled = true;}
976     Signal!(int) onTest;
977     onTest ~= &first;
978     onTest ~= &second;
979     onTest(0);
980     assert(!secondCalled);
981     onTest.disconnect(&first);
982     onTest ~= &first;
983     onTest(0);
984     assert(secondCalled);
985 }
986 
987 unittest
988 {
989     @safe void second(int i) {}
990     Signal!(int) onTest;
991     auto t1 = onTest.getCallable(&second);
992     auto t2 = onTest.getCallable(&second);
993     auto t3 = onTest.getCallable(&second);
994     assert(t1 == t2);
995     assert(t2 == t3);
996 }
997 
998 unittest
999 {
1000     bool called = false;
1001     @safe void handler() { called = true; };
1002     Signal!() onTest;
1003     onTest ~= &handler;
1004     onTest();
1005     assert(called);
1006     called = false;
1007     onTest.enabled = false;
1008     onTest();
1009     assert(!called);
1010     onTest.enabled = true;
1011     onTest();
1012     assert(called);
1013 }
1014 
1015 unittest
1016 {
1017     @safe void handler() {};
1018     Signal!() onTest;
1019     assert(!onTest.isConnected(&handler));
1020     onTest ~= &handler;
1021     assert(onTest.isConnected(&handler));
1022     onTest();
1023     assert(onTest.isConnected(&handler));
1024     onTest.disconnect(&handler);
1025     assert(!onTest.isConnected(&handler));
1026     onTest();
1027     assert(!onTest.isConnected(&handler));
1028 }
1029 
1030 unittest
1031 {
1032     bool firstCalled, secondCalled, thirdCalled;
1033     @safe void handler1() {firstCalled = true;}
1034     @safe void handler2()
1035     {
1036         secondCalled = true;
1037         assert(firstCalled);
1038         assert(thirdCalled);
1039     }
1040     @safe void handler3()
1041     {
1042         thirdCalled = true;
1043         assert(firstCalled);
1044         assert(!secondCalled);
1045     }
1046     Signal!() onTest;
1047     onTest ~= &handler1;
1048     onTest ~= &handler2;
1049     auto h = onTest.connectAfter(&handler1, &handler3);
1050     assert(h == &handler3);
1051     onTest();
1052     assert(firstCalled && secondCalled && thirdCalled);
1053 }
1054 
1055 unittest
1056 {
1057     bool firstCalled, secondCalled;
1058     @safe void handler1() {firstCalled = true;}
1059     @safe void handler2()
1060     {
1061         secondCalled = true;
1062         assert(firstCalled);
1063     }
1064     Signal!() onTest;
1065     onTest ~= &handler2;
1066     onTest.connectFirst(&handler1);
1067     onTest();
1068     assert(firstCalled && secondCalled);
1069 }
1070 
1071 unittest
1072 {
1073     bool firstCalled, secondCalled, thirdCalled;
1074     @safe void handler1() {firstCalled = true;}
1075     @safe void handler2()
1076     {
1077         secondCalled = true;
1078         assert(firstCalled);
1079         assert(!thirdCalled);
1080     }
1081     @safe void handler3()
1082     {
1083         thirdCalled = true;
1084         assert(firstCalled);
1085         assert(secondCalled);
1086     }
1087     Signal!() onTest;
1088     onTest ~= &handler2;
1089     auto h = onTest.connectAfter(&handler2, &handler3);
1090     assert(h == &handler3);
1091     auto h2 = onTest.connectBefore(&handler2, &handler1);
1092     assert(h2 == &handler1);
1093     onTest();
1094     assert(firstCalled && secondCalled && thirdCalled);
1095     firstCalled = secondCalled = thirdCalled = false;
1096     onTest.disconnect(h);
1097     onTest.disconnect(h2);
1098     onTest.disconnect(&handler2);
1099     onTest ~= &handler1;
1100     onTest ~= &handler3;
1101     onTest.connectBefore(&handler3, &handler2);
1102     onTest();
1103     assert(firstCalled && secondCalled && thirdCalled);
1104 }
1105 
1106 unittest
1107 {
1108     @safe void handler() {};
1109     Signal!() onTest;
1110     assert(onTest.calculateLength() == 0);
1111     onTest.connect(&handler);
1112     assert(onTest.calculateLength() == 1);
1113     onTest.clear();
1114     assert(onTest.calculateLength() == 0);
1115     onTest();
1116 }