167 lines
5.2 KiB
C
167 lines
5.2 KiB
C
|
|
||
|
#if !defined( INCLUDED_ISIGNAL_H )
|
||
|
#define INCLUDED_ISIGNAL_H
|
||
|
|
||
|
#include "generic/callback.h"
|
||
|
#include "signal/signalfwd.h"
|
||
|
|
||
|
class SignalHandlerResult
|
||
|
{
|
||
|
bool value;
|
||
|
public:
|
||
|
explicit SignalHandlerResult( bool value ) : value( value ){
|
||
|
}
|
||
|
bool operator==( SignalHandlerResult other ) const {
|
||
|
return value == other.value;
|
||
|
}
|
||
|
bool operator!=( SignalHandlerResult other ) const {
|
||
|
return !operator==( other );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const SignalHandlerResult SIGNAL_CONTINUE_EMISSION = SignalHandlerResult( false );
|
||
|
const SignalHandlerResult SIGNAL_STOP_EMISSION = SignalHandlerResult( true );
|
||
|
|
||
|
template<class Caller, class F>
|
||
|
class SignalHandlerCallerN;
|
||
|
|
||
|
template<class Caller, class R, class... Ts>
|
||
|
class SignalHandlerCallerN<Caller, R(Ts...)> {
|
||
|
public:
|
||
|
using func = SignalHandlerResult(Ts...);
|
||
|
|
||
|
static SignalHandlerResult call(Ts... args) {
|
||
|
Caller::call(args...);
|
||
|
return SIGNAL_CONTINUE_EMISSION;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<class Caller>
|
||
|
using SignalHandlerCaller = SignalHandlerCallerN<Caller, get_func<Caller>>;
|
||
|
|
||
|
template<class Caller>
|
||
|
using SignalHandlerCaller1 = SignalHandlerCaller<Caller>;
|
||
|
|
||
|
template<class Caller>
|
||
|
using SignalHandlerCaller2 = SignalHandlerCaller<Caller>;
|
||
|
|
||
|
template<typename Caller>
|
||
|
using SignalHandlerCaller3 = SignalHandlerCaller<Caller>;
|
||
|
|
||
|
template<typename Caller>
|
||
|
using SignalHandlerCaller4 = SignalHandlerCaller<Caller>;
|
||
|
|
||
|
template<typename Other, typename True, typename False, typename Type>
|
||
|
class TypeEqual {
|
||
|
public:
|
||
|
using type = False;
|
||
|
};
|
||
|
|
||
|
template<typename Other, typename True, typename False>
|
||
|
class TypeEqual<Other, True, False, Other> {
|
||
|
public:
|
||
|
using type = True;
|
||
|
};
|
||
|
|
||
|
template<class CB, template<class T> class Wrapper>
|
||
|
class SignalHandlerN : public CB {
|
||
|
public:
|
||
|
template<typename Caller>
|
||
|
SignalHandlerN(const BindFirstOpaque<Caller> &caller)
|
||
|
: CB(BindFirstOpaque<typename TypeEqual<
|
||
|
SignalHandlerResult,
|
||
|
Caller,
|
||
|
Wrapper<Caller>,
|
||
|
get_result_type<Caller>
|
||
|
>::type>(caller.getBound())) {
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class SignalHandler : public SignalHandlerN<Callback<SignalHandlerResult()>, SignalHandlerCaller1> {
|
||
|
using SignalHandlerN<Callback<SignalHandlerResult()>, SignalHandlerCaller1>::SignalHandlerN;
|
||
|
};
|
||
|
|
||
|
template<typename Caller>
|
||
|
inline SignalHandler makeSignalHandler( const BindFirstOpaque<Caller>& caller ){
|
||
|
return SignalHandler( caller );
|
||
|
}
|
||
|
template<typename Caller>
|
||
|
inline SignalHandler makeSignalHandler(const Caller &caller, get_argument<Caller, 0> callee) {
|
||
|
return SignalHandler( BindFirstOpaque<Caller>( callee ) );
|
||
|
}
|
||
|
|
||
|
template<typename FirstArgument>
|
||
|
class SignalHandler1 : public SignalHandlerN<Callback<SignalHandlerResult(FirstArgument)>, SignalHandlerCaller2> {
|
||
|
using SignalHandlerN<Callback<SignalHandlerResult(FirstArgument)>, SignalHandlerCaller2>::SignalHandlerN;
|
||
|
};
|
||
|
|
||
|
template<typename Caller>
|
||
|
inline SignalHandler1<get_argument<Caller, 1>> makeSignalHandler1(const BindFirstOpaque<Caller> &caller) {
|
||
|
return SignalHandler1<get_argument<Caller, 1>>(caller);
|
||
|
}
|
||
|
template<typename Caller>
|
||
|
inline SignalHandler1<get_argument<Caller, 1>>
|
||
|
makeSignalHandler1(const Caller &caller, get_argument<Caller, 0> callee) {
|
||
|
return SignalHandler1<get_argument<Caller, 1>>(BindFirstOpaque<Caller>(callee));
|
||
|
}
|
||
|
|
||
|
template<typename FirstArgument, typename SecondArgument>
|
||
|
class SignalHandler2
|
||
|
: public SignalHandlerN<Callback<SignalHandlerResult(FirstArgument, SecondArgument)>, SignalHandlerCaller3> {
|
||
|
using SignalHandlerN<Callback<SignalHandlerResult(FirstArgument, SecondArgument)>, SignalHandlerCaller3>::SignalHandlerN;
|
||
|
};
|
||
|
|
||
|
template<typename Caller>
|
||
|
inline SignalHandler2<
|
||
|
get_argument<Caller, 1>,
|
||
|
get_argument<Caller, 2>
|
||
|
> makeSignalHandler2(const BindFirstOpaque<Caller> &caller) {
|
||
|
return SignalHandler2<
|
||
|
get_argument<Caller, 1>,
|
||
|
get_argument<Caller, 2>
|
||
|
>( caller );
|
||
|
}
|
||
|
template<typename Caller>
|
||
|
inline SignalHandler2<
|
||
|
get_argument<Caller, 1>,
|
||
|
get_argument<Caller, 2>
|
||
|
> makeSignalHandler2(const Caller &caller, get_argument<Caller, 0> callee) {
|
||
|
return SignalHandler2<
|
||
|
get_argument<Caller, 1>,
|
||
|
get_argument<Caller, 2>
|
||
|
>(BindFirstOpaque<Caller>(callee));
|
||
|
}
|
||
|
|
||
|
template<typename FirstArgument, typename SecondArgument, typename ThirdArgument>
|
||
|
class SignalHandler3
|
||
|
: public SignalHandlerN<Callback<SignalHandlerResult(FirstArgument, SecondArgument, ThirdArgument)>, SignalHandlerCaller4> {
|
||
|
using SignalHandlerN<Callback<SignalHandlerResult(FirstArgument, SecondArgument, ThirdArgument)>, SignalHandlerCaller4>::SignalHandlerN;
|
||
|
};
|
||
|
|
||
|
template<typename Caller>
|
||
|
inline SignalHandler3<
|
||
|
get_argument<Caller, 1>,
|
||
|
get_argument<Caller, 2>,
|
||
|
get_argument<Caller, 3>
|
||
|
> makeSignalHandler3(const BindFirstOpaque<Caller> &caller) {
|
||
|
return SignalHandler3<
|
||
|
get_argument<Caller, 1>,
|
||
|
get_argument<Caller, 2>,
|
||
|
get_argument<Caller, 3>
|
||
|
>( caller );
|
||
|
}
|
||
|
template<typename Caller>
|
||
|
inline SignalHandler3<
|
||
|
get_argument<Caller, 1>,
|
||
|
get_argument<Caller, 2>,
|
||
|
get_argument<Caller, 3>
|
||
|
> makeSignalHandler3(const Caller &caller, get_argument<Caller, 0> callee) {
|
||
|
return SignalHandler3<
|
||
|
get_argument<Caller, 1>,
|
||
|
get_argument<Caller, 2>,
|
||
|
get_argument<Caller, 3>
|
||
|
>(BindFirstOpaque<Caller>(callee));
|
||
|
}
|
||
|
|
||
|
#endif
|