worldspawn/libs/signal/isignal.h
2020-11-17 12:16:16 +01:00

166 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