1 module tinyevent; 2 3 /// Defines a regular event 4 alias Event(Args...) = void delegate(Args) @safe []; 5 /// Defines a cancelable event by returning false to cancel 6 alias Cancelable(Args...) = bool delegate(Args) @safe []; 7 8 /// Calls all functions in a regular event 9 void emit(T : void delegate(Args), Args...)(T[] events, Args args) { 10 foreach(fn; events) 11 fn(args); 12 } 13 14 /// Calls all functions in a cancelable event 15 bool emit(T : bool delegate(Args), Args...)(T[] events, Args args) { 16 foreach(fn; events) 17 if(!fn(args)) 18 return false; 19 return true; 20 } 21 22 /// Returns true if the type or variable is an Event!(...) 23 enum bool isEvent(T) = is(T : U[], U) && is(U : void delegate (Args), Args...); 24 /// Returns true if the type or variable is a Cancelable!(...) 25 enum bool isCancelable(T) = is(T : U[], U) && is(U : bool delegate (Args), Args...); 26 /// Returns true if the type or variable is an Event or Cancelable 27 enum bool isEmittable(T) = isEvent!T || isCancelable!T; 28 29 /// 30 unittest { 31 Event!string onStringChange; 32 static assert (isEvent!(typeof(onStringChange))); 33 static assert (!isCancelable!(typeof(onStringChange))); 34 static assert (isEmittable!(typeof(onStringChange))); 35 onStringChange ~= (s) { assert(s == "Foo"); }; 36 onStringChange.emit("Foo"); 37 } 38 39 /// 40 unittest { 41 Cancelable!int onIntChange; 42 static assert (!isEvent!(typeof(onIntChange))); 43 static assert (isCancelable!(typeof(onIntChange))); 44 static assert (isEmittable!(typeof(onIntChange))); 45 int changed = 0; 46 onIntChange ~= (i) { if(i > 5) return false; changed++; return true; }; 47 onIntChange ~= (i) { if(i > 4) return false; changed++; return true; }; 48 onIntChange ~= (i) { if(i > 3) return false; changed++; return true; }; 49 assert(onIntChange.emit(2)); 50 assert(changed == 3); 51 52 changed = 0; 53 assert(!onIntChange.emit(4)); 54 assert(changed == 2); 55 } 56 57 // safety tests 58 @system unittest { 59 void delegate(string, int, bool) @system [] eventSystem; 60 eventSystem.emit("", 1, true); 61 } 62 63 @safe unittest { 64 void delegate(string, int, bool) @trusted [] eventTrusted; 65 eventTrusted.emit("", 1, true); 66 void delegate(string, int, bool) @safe [] eventSafe; 67 eventSafe.emit("", 1, true); 68 } 69 70 @safe nothrow unittest { 71 void delegate(string, int, bool) @safe nothrow [] eventSafe; 72 eventSafe.emit("", 1, true); 73 } 74 75 unittest { 76 string s; 77 static assert (!isEvent!(typeof(s))); 78 int i; 79 static assert (!isEvent!(typeof(i))); 80 void fn(int i) { 81 } 82 static assert (!isEvent!(typeof(fn))); 83 static assert (isEvent!(typeof([&fn]))); 84 void function()[] fns; 85 static assert (!isEvent!(typeof(fns))); 86 void delegate()[] dels; 87 static assert (isEvent!(typeof(dels))); 88 Event!int e; 89 static assert (isEvent!(typeof(e))); 90 Cancelable!int c; 91 static assert (isCancelable!(typeof(c))); 92 static assert (isEmittable!(typeof(e)) && isEmittable!(typeof(c))); 93 Event!() en; 94 static assert (isEvent!(typeof(en))); 95 Cancelable!() cn; 96 static assert (isCancelable!(typeof(cn))); 97 Event!(Event!int, int, string, Object) em; 98 static assert (isEvent!(typeof(em))); 99 Cancelable!(Object, string, void function(int, string)) cm; 100 static assert (isCancelable!(typeof(cm))); 101 }