1 
2 #if !defined( INCLUDED_ISIGNAL_H )
3 #define INCLUDED_ISIGNAL_H
4 
5 #include "generic/callback.h"
6 #include "signal/signalfwd.h"
7 
8 class SignalHandlerResult
9 {
10 bool value;
11 public:
SignalHandlerResult(bool value)12 explicit SignalHandlerResult( bool value ) : value( value ){
13 }
14 bool operator==( SignalHandlerResult other ) const {
15 	return value == other.value;
16 }
17 bool operator!=( SignalHandlerResult other ) const {
18 	return !operator==( other );
19 }
20 };
21 
22 const SignalHandlerResult SIGNAL_CONTINUE_EMISSION = SignalHandlerResult( false );
23 const SignalHandlerResult SIGNAL_STOP_EMISSION = SignalHandlerResult( true );
24 
25 template<typename Caller>
26 class SignalHandlerCaller1
27 {
28 public:
29 typedef typename Caller::first_argument_type first_argument_type;
30 typedef SignalHandlerResult result_type;
call(first_argument_type a1)31 static result_type call( first_argument_type a1 ){
32 	Caller::call( a1 );
33 	return SIGNAL_CONTINUE_EMISSION;
34 }
35 };
36 
37 template<typename Caller>
38 class SignalHandlerCaller2
39 {
40 public:
41 typedef typename Caller::first_argument_type first_argument_type;
42 typedef typename Caller::second_argument_type second_argument_type;
43 typedef SignalHandlerResult result_type;
call(first_argument_type a1,second_argument_type a2)44 static result_type call( first_argument_type a1, second_argument_type a2 ){
45 	Caller::call( a1, a2 );
46 	return SIGNAL_CONTINUE_EMISSION;
47 }
48 };
49 
50 template<typename Caller>
51 class SignalHandlerCaller3
52 {
53 public:
54 typedef typename Caller::first_argument_type first_argument_type;
55 typedef typename Caller::second_argument_type second_argument_type;
56 typedef typename Caller::third_argument_type third_argument_type;
57 typedef SignalHandlerResult result_type;
call(first_argument_type a1,second_argument_type a2,third_argument_type a3)58 static result_type call( first_argument_type a1, second_argument_type a2, third_argument_type a3 ){
59 	Caller::call( a1, a2, a3 );
60 	return SIGNAL_CONTINUE_EMISSION;
61 }
62 };
63 
64 template<typename Caller>
65 class SignalHandlerCaller4
66 {
67 public:
68 typedef typename Caller::first_argument_type first_argument_type;
69 typedef typename Caller::second_argument_type second_argument_type;
70 typedef typename Caller::third_argument_type third_argument_type;
71 typedef typename Caller::fourth_argument_type fourth_argument_type;
72 typedef SignalHandlerResult result_type;
call(first_argument_type a1,second_argument_type a2,third_argument_type a3,fourth_argument_type a4)73 static result_type call( first_argument_type a1, second_argument_type a2, third_argument_type a3, fourth_argument_type a4 ){
74 	Caller::call( a1, a2, a3, a4 );
75 	return SIGNAL_CONTINUE_EMISSION;
76 }
77 };
78 
79 class SignalHandler : public Callback0<SignalHandlerResult>
80 {
81 public:
82 template<typename Caller>
SignalHandler(const BindFirstOpaque<Caller> & caller)83 SignalHandler( const BindFirstOpaque<Caller>& caller )
84 	: Callback0<SignalHandlerResult>( BindFirstOpaque<typename TypeEqual<
85 														  SignalHandlerResult,
86 														  Caller,
87 														  SignalHandlerCaller1<Caller>,
88 														  typename Caller::result_type
89 														  >::type>( caller.getBound() ) ){
90 }
91 };
92 
93 template<typename Caller>
makeSignalHandler(const BindFirstOpaque<Caller> & caller)94 inline SignalHandler makeSignalHandler( const BindFirstOpaque<Caller>& caller ){
95 	return SignalHandler( caller );
96 }
97 template<typename Caller>
makeSignalHandler(const Caller & caller,typename Caller::first_argument_type callee)98 inline SignalHandler makeSignalHandler( const Caller& caller, typename Caller::first_argument_type callee ){
99 	return SignalHandler( BindFirstOpaque<Caller>( callee ) );
100 }
101 
102 
103 template<typename FirstArgument>
104 class SignalHandler1 : public Callback1<FirstArgument, SignalHandlerResult>
105 {
106 public:
107 template<typename Caller>
SignalHandler1(const BindFirstOpaque1<Caller> & caller)108 SignalHandler1( const BindFirstOpaque1<Caller>& caller )
109 	: Callback1<FirstArgument, SignalHandlerResult>( BindFirstOpaque1<typename TypeEqual<
110 																		  SignalHandlerResult,
111 																		  Caller,
112 																		  SignalHandlerCaller2<Caller>,
113 																		  typename Caller::result_type
114 																		  >::type>( caller.getBound() ) ){
115 }
116 };
117 
118 template<typename Caller>
makeSignalHandler1(const BindFirstOpaque1<Caller> & caller)119 inline SignalHandler1<typename Caller::second_argument_type> makeSignalHandler1( const BindFirstOpaque1<Caller>& caller ){
120 	return SignalHandler1<typename Caller::second_argument_type>( caller );
121 }
122 template<typename Caller>
makeSignalHandler1(const Caller & caller,typename Caller::first_argument_type callee)123 inline SignalHandler1<typename Caller::second_argument_type> makeSignalHandler1( const Caller& caller, typename Caller::first_argument_type callee ){
124 	return SignalHandler1<typename Caller::second_argument_type>( BindFirstOpaque1<Caller>( callee ) );
125 }
126 
127 
128 template<typename FirstArgument, typename SecondArgument>
129 class SignalHandler2 : public Callback2<FirstArgument, SecondArgument, SignalHandlerResult>
130 {
131 public:
132 template<typename Caller>
SignalHandler2(const BindFirstOpaque2<Caller> & caller)133 SignalHandler2( const BindFirstOpaque2<Caller>& caller )
134 	: Callback2<FirstArgument, SecondArgument, SignalHandlerResult>( BindFirstOpaque2<typename TypeEqual<
135 																						  SignalHandlerResult,
136 																						  Caller,
137 																						  SignalHandlerCaller3<Caller>,
138 																						  typename Caller::result_type
139 																						  >::type>( caller.getBound() ) ){
140 }
141 };
142 
143 template<typename Caller>
144 inline SignalHandler2<
145 	typename Caller::second_argument_type,
146 	typename Caller::third_argument_type
makeSignalHandler2(const BindFirstOpaque2<Caller> & caller)147 	> makeSignalHandler2( const BindFirstOpaque2<Caller>& caller ){
148 	return SignalHandler2<
149 			   typename Caller::second_argument_type,
150 			   typename Caller::third_argument_type
151 			   >( caller );
152 }
153 template<typename Caller>
154 inline SignalHandler2<
155 	typename Caller::second_argument_type,
156 	typename Caller::third_argument_type
makeSignalHandler2(const Caller & caller,typename Caller::first_argument_type callee)157 	> makeSignalHandler2( const Caller& caller, typename Caller::first_argument_type callee ){
158 	return SignalHandler2<
159 			   typename Caller::second_argument_type,
160 			   typename Caller::third_argument_type
161 			   >( BindFirstOpaque2<Caller>( callee ) );
162 }
163 
164 
165 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument>
166 class SignalHandler3 : public Callback3<FirstArgument, SecondArgument, ThirdArgument, SignalHandlerResult>
167 {
168 public:
169 template<typename Caller>
SignalHandler3(const BindFirstOpaque3<Caller> & caller)170 SignalHandler3( const BindFirstOpaque3<Caller>& caller )
171 	: Callback3<FirstArgument, SecondArgument, ThirdArgument, SignalHandlerResult>( BindFirstOpaque3<typename TypeEqual<
172 																										 SignalHandlerResult,
173 																										 Caller,
174 																										 SignalHandlerCaller4<Caller>,
175 																										 typename Caller::result_type
176 																										 >::type>( caller.getBound() ) ){
177 }
178 };
179 
180 template<typename Caller>
181 inline SignalHandler3<
182 	typename Caller::second_argument_type,
183 	typename Caller::third_argument_type,
184 	typename Caller::fourth_argument_type
makeSignalHandler3(const BindFirstOpaque3<Caller> & caller)185 	> makeSignalHandler3( const BindFirstOpaque3<Caller>& caller ){
186 	return SignalHandler3<
187 			   typename Caller::second_argument_type,
188 			   typename Caller::third_argument_type,
189 			   typename Caller::fourth_argument_type
190 			   >( caller );
191 }
192 template<typename Caller>
193 inline SignalHandler3<
194 	typename Caller::second_argument_type,
195 	typename Caller::third_argument_type,
196 	typename Caller::fourth_argument_type
makeSignalHandler3(const Caller & caller,typename Caller::first_argument_type callee)197 	> makeSignalHandler3( const Caller& caller, typename Caller::first_argument_type callee ){
198 	return SignalHandler3<
199 			   typename Caller::second_argument_type,
200 			   typename Caller::third_argument_type,
201 			   typename Caller::fourth_argument_type
202 			   >( BindFirstOpaque3<Caller>( callee ) );
203 }
204 
205 #endif
206