Ho un oggetto che funziona in un ciclo infinito. Lo main()
crea un'istanza dell'oggetto e chiama il metodo run()
. Dal momento che non voglio usare i thread, ho bisogno di una soluzione per far sì che il mio oggetto smetta di funzionare. Sotto vedi quello che ho scoperto.Segnali di cattura: utilizzare una funzione membro come gestore di segnale
struct Foo
{
void run()
{
running = 1;
while (running)
do_something_useful();
std::cout << "Execution stopped." << std::endl;
}
bool running;
void catch_signal(int signal)
{
std::cout << "Caught signal " << signal << std::endl;
if(signal == SIGTERM)
running = false;
}
};
Come si vede, ho bisogno di inviare un segnale in modo asincrono. Pertanto, io uso un gestore di segnale e sigaction
. Sotto il main
posso immaginare di usare.
int main(int argc, char** argv)
{
Foo foo;
struct sigaction sigIntHandler;
boost::function< void (int) > f;
f = std::bind1st(
std::mem_fun(&Foo::catch_signal), &foo);
f(5); // this call works
sigIntHandler.sa_handler = f; // compiler complains, "cannot assign ..."
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGTERM, &sigIntHandler, NULL);
s.run();
}
Cosa mi aspetto ora: il programma viene eseguito fino a quando io mando SIGTERM
che viene catturata e farà sì che il mio oggetto di fermare l'iterazione e tornare alla principale.
Ho due domande ora:
(a) il codice che vedi una linea contrassegnata con "compilatore si lamenta", il messaggio è come
boost::function<void(int)> cannot be converted to __sighandler_t {aka void (*)(int)}
Di cosa ho bisogno di cambiare per rendere questo lavoro? Penso che f
sia come void f(int)
, come le funzioni che il gestore di segnali riceve in alcuni esempi.
(b) Per quelli di voi che si chiedono "cosa sta facendo quel ragazzo?": Avete qualche consiglio su come risolvere meglio questo tipo di cose?
Solo per curiosità, perché non desideri utilizzare i thread?Anche se non ho usato boost, suppongo che si aspetti una funzione di callback da fornire. – M4rc
Come avviare '' Foo :: run() '' in una discussione, catturando il segnale in '' main'' e lasciare che la chiamata principale sth. come '' thread.terminate() ''? Sì, sarebbe una possibilità, ma ho pensato che sarebbe stato troppo per questo. –
Questo è un modo per sicuro. L'altro che (nel mio miasma di pensiero sedato) è che si può avere una struttura con qualsiasi informazione in essa necessaria, registrarla come thread, in modo da eseguire il ciclo con le normali funzioni principali al suo interno e il gestore di segnale in esecuzione sul proprio thread, quindi prendi il valore byref per vedere se è successo un evento, e in tal caso quale evento e la risposta appropriata. – M4rc