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