1 module des.flow.event; 2 3 import std.traits; 4 import std..string : format; 5 6 import core.time; 7 8 import des.util.data.pdata; 9 10 import des.flow.base; 11 import des.flow.sysevdata; 12 13 /// Pass data between threads 14 struct Event 15 { 16 /// `ulong.max` reserved system event code 17 enum system_code = ulong.max; 18 19 alias typeof(this) Self; 20 21 /// 22 ulong code; 23 24 /// 25 ulong timestamp; 26 27 /// information in event 28 PData data; 29 30 /++ generate system event 31 returns: 32 Event 33 +/ 34 static auto system( SysEvData sed ) 35 { 36 Self ev; 37 ev.code = system_code; 38 ev.timestamp = currentTick; 39 ev.data = PData(sed); 40 return ev; 41 } 42 43 /// 44 this(T)( ulong code, in T value ) 45 if( is( typeof(PData(value)) ) ) 46 in { assert( code != system_code ); } body 47 { 48 this.code = code; 49 timestamp = currentTick; 50 data = PData(value); 51 } 52 53 private enum base_ctor = 54 q{ 55 this( in Event ev ) %s 56 { 57 code = ev.code; 58 timestamp = ev.timestamp; 59 data = ev.data; 60 } 61 }; 62 63 mixin( format( base_ctor, "" ) ); 64 mixin( format( base_ctor, "const" ) ); 65 mixin( format( base_ctor, "immutable" ) ); 66 mixin( format( base_ctor, "shared" ) ); 67 mixin( format( base_ctor, "shared const" ) ); 68 69 @property 70 { 71 /// 72 bool isSystem() pure const 73 { return code == system_code; } 74 75 /// elapsed time before create event 76 ulong elapsed() const 77 { return currentTick - timestamp; } 78 79 /// get data as type T 80 T as(T)() const { return data.as!T; } 81 /// get data as type T 82 T as(T)() shared const { return data.as!T; } 83 /// get data as type T 84 T as(T)() immutable { return data.as!T; } 85 86 /// get pdata 87 immutable(void)[] pdata() const { return data.data; } 88 /// get pdata 89 immutable(void)[] pdata() shared const { return data.data; } 90 /// get pdata 91 immutable(void)[] pdata() immutable { return data.data; } 92 } 93 } 94 95 /// 96 interface EventProcessor { /++ +/ void processEvent( in Event ); } 97 98 /// 99 interface EventBus { /++ +/ void pushEvent( in Event ); } 100 101 /// 102 unittest 103 { 104 auto a = Event( 1, [ 0.1, 0.2, 0.3 ] ); 105 auto gg = a.as!(double[]); 106 assert( gg == [ 0.1, 0.2, 0.3 ] ); 107 auto b = Event( 1, "some string"w ); 108 auto nn = b.as!wstring; 109 assert( nn == "some string"w ); 110 auto c = Event( 1, "some str" ); 111 auto d = shared Event( c ); 112 assert( c.as!string == "some str" ); 113 assert( d.as!string == "some str" ); 114 assert( c.code == d.code ); 115 116 struct TestStruct { double x, y; string info; immutable(int)[] data; } 117 118 auto ts = TestStruct( 10.1, 12.3, "hello", [1,2,3,4] ); 119 auto e = Event( 1, ts ); 120 121 auto f = shared Event( e ); 122 auto g = immutable Event( e ); 123 auto h = shared const Event( e ); 124 125 assert( e.as!TestStruct == ts ); 126 assert( f.as!TestStruct == ts ); 127 assert( g.as!TestStruct == ts ); 128 assert( h.as!TestStruct == ts ); 129 130 auto l = Event( f ); 131 auto m = Event( g ); 132 auto n = Event( h ); 133 134 assert( l.as!TestStruct == ts ); 135 assert( m.as!TestStruct == ts ); 136 assert( n.as!TestStruct == ts ); 137 } 138 139 unittest 140 { 141 auto a = Event( 1, [ 0.1, 0.2, 0.3 ] ); 142 assert( !a.isSystem ); 143 auto b = Event.system( SysEvData.init ); 144 assert( b.isSystem ); 145 } 146 147 unittest 148 { 149 static class Test { int[string] info; } 150 static assert( !__traits(compiles,PData(0,new Test)) ); 151 } 152 153 unittest 154 { 155 import std.conv; 156 import std..string; 157 158 static class Test 159 { 160 int[string] info; 161 162 static Test load( in void[] data ) 163 { 164 auto str = cast(string)data.dup; 165 auto elems = str.split(","); 166 int[string] buf; 167 foreach( elem; elems ) 168 { 169 auto key = elem.split(":")[0]; 170 auto val = to!int( elem.split(":")[1] ); 171 buf[key] = val; 172 } 173 return new Test( buf ); 174 } 175 176 this( in int[string] I ) 177 { 178 foreach( key, val; I ) 179 info[key] = val; 180 info.rehash(); 181 } 182 183 auto dump() const 184 { 185 string[] buf; 186 foreach( key, val; info ) buf ~= format( "%s:%s", key, val ); 187 return cast(immutable(void)[])( buf.join(",").idup ); 188 } 189 } 190 191 auto tt = new Test( [ "ok":1, "no":3, "yes":5 ] ); 192 auto a = Event( 1, tt.dump() ); 193 auto ft = Test.load( a.data ); 194 assert( tt.info == ft.info ); 195 tt.info.remove("yes"); 196 assert( tt.info != ft.info ); 197 198 auto b = Event( 1, "ok:1,no:3" ); 199 auto ft2 = Test.load( b.data ); 200 assert( tt.info == ft2.info ); 201 } 202 203 /// 204 unittest 205 { 206 static struct TestStruct { double x, y; string info; immutable(int)[] data; } 207 auto ts = TestStruct( 3.14, 2.7, "hello", [ 2, 3, 4 ] ); 208 209 auto a = Event( 8, ts ); 210 auto ac = const Event( a ); 211 auto ai = immutable Event( a ); 212 auto as = shared Event( a ); 213 auto acs = const shared Event( a ); 214 215 assert( a.as!TestStruct == ts ); 216 assert( ac.as!TestStruct == ts ); 217 assert( ai.as!TestStruct == ts ); 218 assert( as.as!TestStruct == ts ); 219 assert( acs.as!TestStruct == ts ); 220 }