]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/signal/isignal.h
c447d71bc13a30a1a12b4508f8c4579267b09c3d
[xonotic/netradiant.git] / libs / signal / isignal.h
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:
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<class Caller, class F>
26 class SignalHandlerCallerN;
27
28 template<class Caller, class R, class... Ts>
29 class SignalHandlerCallerN<Caller, R(Ts...)> {
30 public:
31     using func = SignalHandlerResult(Ts...);
32
33     static SignalHandlerResult call(Ts... args) {
34         Caller::call(args...);
35         return SIGNAL_CONTINUE_EMISSION;
36     }
37 };
38
39 template<class Caller>
40 using SignalHandlerCaller = SignalHandlerCallerN<Caller, typename Caller::func>;
41
42 template<class Caller>
43 using SignalHandlerCaller1 = SignalHandlerCaller<Caller>;
44
45 template<class Caller>
46 using SignalHandlerCaller2 = SignalHandlerCaller<Caller>;
47
48 template<typename Caller>
49 using SignalHandlerCaller3 = SignalHandlerCaller<Caller>;
50
51 template<typename Caller>
52 using SignalHandlerCaller4 = SignalHandlerCaller<Caller>;
53
54 template<typename Other, typename True, typename False, typename Type>
55 class TypeEqual {
56 public:
57     using type = False;
58 };
59
60 template<typename Other, typename True, typename False>
61 class TypeEqual<Other, True, False, Other> {
62 public:
63     using type = True;
64 };
65
66 template<class CB, template<class T> class Wrapper>
67 class SignalHandlerN : public CB {
68 public:
69     template<typename Caller>
70     SignalHandlerN(const BindFirstOpaque<Caller> &caller)
71             : CB(BindFirstOpaque<typename TypeEqual<
72             SignalHandlerResult,
73             Caller,
74             Wrapper<Caller>,
75             get_result_type<Caller>
76     >::type>(caller.getBound())) {
77     }
78 };
79
80 class SignalHandler : public SignalHandlerN<Callback0<SignalHandlerResult>, SignalHandlerCaller1> {
81     using SignalHandlerN<Callback0<SignalHandlerResult>, SignalHandlerCaller1>::SignalHandlerN;
82 };
83
84 template<typename Caller>
85 inline SignalHandler makeSignalHandler( const BindFirstOpaque<Caller>& caller ){
86         return SignalHandler( caller );
87 }
88 template<typename Caller>
89 inline SignalHandler makeSignalHandler(const Caller &caller, get_argument<Caller, 0> callee) {
90         return SignalHandler( BindFirstOpaque<Caller>( callee ) );
91 }
92
93 template<typename FirstArgument>
94 class SignalHandler1 : public SignalHandlerN<Callback1<FirstArgument, SignalHandlerResult>, SignalHandlerCaller2> {
95     using SignalHandlerN<Callback1<FirstArgument, SignalHandlerResult>, SignalHandlerCaller2>::SignalHandlerN;
96 };
97
98 template<typename Caller>
99 inline SignalHandler1<get_argument<Caller, 1>> makeSignalHandler1(const BindFirstOpaque<Caller> &caller) {
100     return SignalHandler1<get_argument<Caller, 1>>(caller);
101 }
102 template<typename Caller>
103 inline SignalHandler1<get_argument<Caller, 1>>
104 makeSignalHandler1(const Caller &caller, get_argument<Caller, 0> callee) {
105     return SignalHandler1<get_argument<Caller, 1>>(BindFirstOpaque<Caller>(callee));
106 }
107
108 template<typename FirstArgument, typename SecondArgument>
109 class SignalHandler2
110         : public SignalHandlerN<Callback2<FirstArgument, SecondArgument, SignalHandlerResult>, SignalHandlerCaller3> {
111     using SignalHandlerN<Callback2<FirstArgument, SecondArgument, SignalHandlerResult>, SignalHandlerCaller3>::SignalHandlerN;
112 };
113
114 template<typename Caller>
115 inline SignalHandler2<
116         get_argument<Caller, 1>,
117         get_argument<Caller, 2>
118 > makeSignalHandler2(const BindFirstOpaque<Caller> &caller) {
119         return SignalHandler2<
120             get_argument<Caller, 1>,
121             get_argument<Caller, 2>
122                            >( caller );
123 }
124 template<typename Caller>
125 inline SignalHandler2<
126         get_argument<Caller, 1>,
127         get_argument<Caller, 2>
128 > makeSignalHandler2(const Caller &caller, get_argument<Caller, 0> callee) {
129         return SignalHandler2<
130             get_argument<Caller, 1>,
131             get_argument<Caller, 2>
132     >(BindFirstOpaque<Caller>(callee));
133 }
134
135 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument>
136 class SignalHandler3
137         : public SignalHandlerN<Callback3<FirstArgument, SecondArgument, ThirdArgument, SignalHandlerResult>, SignalHandlerCaller4> {
138     using SignalHandlerN<Callback3<FirstArgument, SecondArgument, ThirdArgument, SignalHandlerResult>, SignalHandlerCaller4>::SignalHandlerN;
139 };
140
141 template<typename Caller>
142 inline SignalHandler3<
143         get_argument<Caller, 1>,
144         get_argument<Caller, 2>,
145         get_argument<Caller, 3>
146 > makeSignalHandler3(const BindFirstOpaque<Caller> &caller) {
147         return SignalHandler3<
148             get_argument<Caller, 1>,
149             get_argument<Caller, 2>,
150             get_argument<Caller, 3>
151                            >( caller );
152 }
153 template<typename Caller>
154 inline SignalHandler3<
155         get_argument<Caller, 1>,
156         get_argument<Caller, 2>,
157         get_argument<Caller, 3>
158 > makeSignalHandler3(const Caller &caller, get_argument<Caller, 0> callee) {
159         return SignalHandler3<
160             get_argument<Caller, 1>,
161             get_argument<Caller, 2>,
162             get_argument<Caller, 3>
163     >(BindFirstOpaque<Caller>(callee));
164 }
165
166 #endif