1 module des.flow.element;
2 
3 import des.flow.base;
4 
5 import des.flow.event;
6 import des.flow.signal;
7 
8 /++
9 Inner interpret of thread
10 
11 action must be in:
12   * preparation               -> ctor
13   * last actions before start -> process special input event
14   * actions on pause          -> process special input event
15   * processing                -> process
16   * terminate all             -> selfDestroy( external memory manager )
17 +/
18 abstract class WorkElement : EventBus, CtrlSignalBus, ExternalMemoryManager
19 {
20     mixin EMM;
21     mixin ClassLogger;
22 
23 private:
24 
25     ///
26     CtrlSignalProcessor signal_processor;
27 
28     ///
29     EventProcessor event_listener;
30 
31 public:
32 
33     /// main work function
34     abstract void process();
35 
36     ///
37     EventProcessor[] getEventProcessors() { return []; }
38 
39     ///
40     final void setEventListener( EventProcessor ep )
41     {
42         event_listener = ep;
43         logger.Debug( "set event listener [%s]", ep );
44     }
45 
46     /// push event to event listener if it exists
47     final void pushEvent( in Event ev )
48     {
49         logger.trace( "push event with code [%d] timestamp [%d] to listener [%s]", ev.code, ev.timestamp, event_listener );
50         if( event_listener !is null )
51             event_listener.processEvent( ev );
52     }
53 
54     ///
55     final void setCtrlSignalProcessor( CtrlSignalProcessor sp )
56     in { assert( sp !is null ); } body
57     {
58         signal_processor = sp;
59         logger.Debug( "set signal processor [%s]", sp );
60     }
61 
62     /// send signal to signal processor if it exists
63     final void sendCtrlSignal( in CtrlSignal sg )
64     {
65         logger.trace( "send signal [%s] to processor [%s]", sg, signal_processor );
66         if( signal_processor !is null )
67             signal_processor.processCtrlSignal( sg );
68     }
69 }
70 
71 ///
72 unittest
73 {
74     struct TestStruct { double x, y; string info; immutable(int)[] data; }
75     auto ts = TestStruct( 3.14, 2.7, "hello", [ 2, 3, 4 ] );
76 
77     class TestElement: WorkElement
78     {
79         override void process(){}
80     }
81 
82     class TestSignalProcessor : CtrlSignalProcessor
83     { void processCtrlSignal( in CtrlSignal s ) { assertEq( s.code, 0 ); } }
84 
85     auto elem = new TestElement;
86     elem.setCtrlSignalProcessor( new TestSignalProcessor );
87 
88     elem.sendCtrlSignal( CtrlSignal(0) );
89 
90     size_t cnt = 0;
91     elem.setEventListener( new class EventProcessor {
92         void processEvent( in Event ev )
93         { cnt++; assertEq( ev.as!TestStruct, ts ); }
94         });
95 
96     auto ev = Event( 8, ts );
97     elem.pushEvent( ev );
98     elem.pushEvent( const Event( ev ) );
99     elem.pushEvent( shared Event( ev ) );
100     elem.pushEvent( immutable Event( ev ) );
101     elem.pushEvent( const shared Event( ev ) );
102     elem.pushEvent( shared const Event( ev ) );
103     elem.pushEvent( immutable shared Event( ev ) );
104     elem.pushEvent( shared immutable Event( ev ) );
105     assertEq( cnt, 8 );
106 }