📄 sig_handler.h
字号:
//// This file is part of the C++ threads library//// Copyright (C) 2001, The C++ threads library team.//// This file creates a mechanism to deliver signals// to a C++ thread.//#ifndef CPP_THREADS_SIGNAL_SYSTEM_H#define CPP_THREADS_SIGNAL_SYSTEM_H#include "systemlib.h"#include <threads/signal_num.h>namespace cpp_threads { /** * This is an internal structure used by the signalling class * to hold data about each registered. */ template<class T,class P=void*,class Ret=void> struct signalling_holder { int s_pid; struct sigaction s_sa; struct sigaction* s_old_handler; T* s_thisptr; Ret (T::*s_handler)(P); P s_param;#if (Ret!=void) Ret s_retVal;#endif }; /** * Signal system in C++ Threads. * * The signal system, converts C style signal mechanism into * a more usable C++ style. What is more useful in this class * above the normal C signalling system, is that the template * structure and the use of the above structure, allows the * user to specify an arbitrary parameter the signal routine * will take. It also allows the user to specify the return * type for the signal handler. * * Methods are also provided to send signals using this scheme * and to obtain the last return value from the signal handler. * * @short Signal system for C++ threads. * @author Orn E. Hanse <oe.hansen@nissamedia.net> */ template<class T,class P=void*,class Ret=void> class signalling { protected: typedef Ret(T::*slot_t)(P); protected: static signalling_holder<T,P,Ret> _holder[_NSIG]; static void signal_catcher(int); public: signalling(); ~signalling(); /** * This will establish all set signal handlers, with extreme * prejudice. It is mainly thought out, to re-establsh the * signal handling system, in case of a C routine altering * them. */ void resetAll(); /** * Connect a signal to a specific class and method. This * will activate signal delivery to a specific class. The * class can be any class, but must have been given when * the instance of this class was created, along with the * return value and parameter of the method. * * Note, that a signal can only be connected to once, * once connected, it must be disconnected before * being used again. The process that actually is * doing the connect, must also be the true * receiver of the signal. As that's process * signal table is changed. * * @param s The signal number to connect to. * @param c A pointer to the class itself. * @param m A reference to the method within that class. * @return True if the signal was connected. */ bool connect(__sign_num,T*,slot_t); /** * This method varies from the above only in the number of parameters * it accepts. It is a link for those who wish to set the flags, and * mask values, as is accepted by sigaction. * * @param s The signal number to connect to. * @param m The mask to use. * @param f The flags to set. * @param c A pointer to the class instance. * @param p A pointer to the method within the class. * @return True if the signal was connected. */ bool connect(__sign_num,sigset_t,int,T*,slot_t); /** * This method will disconnect a connected signal, and return * it to the state it was in, prior to being connected. * * @param s The signal number to disconnect. * @return True if a signal was disconnected. */ bool disconnect(__sign_num); /** * This method will emit a signal (by way of kill) and pass a * parameter to the routine. It will also return to the caller * the return value from the signal handler. * * @param s Signal number to send to process. * @param p The parameter to pass to signal handler. */ void emit(__sign_num,P); /** * This method will obtain the return value, that was given by * the handler. * * @return The return value from the handler. */ Ret retValue(); /** * This method will query if the signal handler is actually * active. * * @return True if the signal handler is processing a request. */ bool signal_active(); }; template<class T,class P,class Ret> signalling_holder<T,P,Ret> signalling<T,P,Ret>::_holder[_NSIG]; template<class T,class P,class Ret> signalling<T,P,Ret>::signalling() { int i; for(i=0;i<_NSIG;i++) _holder[i].s_old_handler = 0; } template<class T,class P,class Ret> signalling<T,P,Ret>::~signalling() { int i; for(i=0;i<_NSIG;i++) disconnect(__sign_num(i)); } template<class T,class P,class Ret> void signalling<T,P,Ret>::signal_catcher(int signal_num_p) { register signalling_holder<T,P,Ret>& refptr = _holder[signal_num_p]; if( (refptr.s_thisptr) && (refptr.s_handler) )#if( Ret!=void ) refptr.s_retVal=(refptr.s_thisptr->*refptr.s_handler)(refptr.s_param);#else (refptr.s_thisptr->*refptr.s_handler)(refptr.s_param);#endif } template<class T,class P,class Ret> void signalling<T,P,Ret>::resetAll() { for(int i=1;i<_NSIG;i++) if( _holder[i].s_old_handler ) sys::sigaction(i,&_holder[i].s_sa,0); } template<class T,class P,class Ret> bool signalling<T,P,Ret>::connect(__sign_num signal_num_p,T* this_p,slot_t handler_p) { sigset_t mask; sigemptyset(&mask); return connect(signal_num_p,mask,0,this_p,handler_p); } template<class T,class P,class Ret> bool signalling<T,P,Ret>::connect(__sign_num signal_num_p,sigset_t mask_p,int flags_p,T* this_p,slot_t handler_p) { int rv; signalling_holder<T,P,Ret>& refptr = _holder[signal_num_p]; refptr.s_handler = handler_p; refptr.s_thisptr = this_p; refptr.s_param = P(); if( refptr.s_old_handler == 0 ) { refptr.s_old_handler = new struct sigaction; refptr.s_sa.sa_handler = signal_catcher; refptr.s_sa.sa_flags = flags_p; refptr.s_sa.sa_mask = mask_p; refptr.s_pid = getpid(); rv=sys::sigaction(signal_num_p,&refptr.s_sa,refptr.s_old_handler); return (rv == 0); } return true; } template<class T,class P,class Ret> bool signalling<T,P,Ret>::disconnect(__sign_num signal_num_p) { signalling_holder<T,P,Ret>& refptr = _holder[signal_num_p]; int n=0; if( refptr.s_old_handler ) { n = sys::sigaction(signal_num_p,refptr.s_old_handler,0); refptr.s_old_handler = 0; } return (n == 0); } template<class T,class P,class Ret> void signalling<T,P,Ret>::emit(__sign_num signal_num_p,P param_p) { signalling_holder<T,P,Ret>& refptr = _holder[signal_num_p]; refptr.s_param = param_p; kill( refptr.s_pid,signal_num_p ); } template<class T,class P,class Ret> Ret retValue(__sign_num signal_num_p) {#if( Ret!=void ) return _holder[signal_num_p].s_retVal;#endif }}; // namespace#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -