2012-07-13 8 views
10

Ho scritto questo programma che ha una funzione principale, al cui interno, sto creando due prese, in questo modo:Utilizzo di Auto e Lambda per gestire il segnale?

int sockfd1 = socket(AF_INET, SOCK_STREAM, 0); 
int sockfd2 = socket(AF_INET, SOCK_STREAM, 0); 

Ora faccio alcune cose con loro, e quando l'utente preme CTRL + C per terminare il processo, voglio per assicurarsi che le prese di chiudere correttamente, in modo da fare questo:

auto sigTermHandler = [&] (int param) { close(sockfd1); close(sockfd2); }; 
signal(SIGTERM, sigTermHandler); 

Ma questo getta il seguente errore di compilazione quando compilato come g++ -std=gnu++0x <filename>.cpp:

error: cannot convert ‘main(int, char**)::<lambda(int)>’ to ‘__sighandler_t {aka void (*)(int)}’ for argument ‘2’ to ‘void (* signal(int, __sighandler_t))(int)’ 

Non è possibile utilizzare lambda in questo modo per gestire i segnali? Si prega di avvisare.

P.S. So che potrei metterlo in un distruttore, se avessi fatto l'OOP corretto, ma sono curioso di vedere se funziona.

risposta

15

Non è possibile utilizzare la funzione di acquisizione da lambda quando si chiama un puntatore a funzione semplice. La norma che una funzione lambda senza cattura è convertibile in un puntatore a funzione, però:

5.1.2 (6) Il tipo di chiusura per una lambda espressione senza lambda-cattura ha un pubblico non virtuale funzione di conversione const- non esplicita per puntare alla funzione con lo stesso parametro e tipi di ritorno dell'operatore di chiamata di funzione del tipo di chiusura. Il valore restituito da questa funzione di conversione deve essere l'indirizzo di una funzione che, invocata, ha lo stesso effetto del richiamo dell'operatore di chiamata di funzione del tipo di chiusura.

Per esempio, questo funziona:

signal(SIGTERM, [](int signum) { /* ... */ }); 

Ma non questa:

signal(SIGTERM, [foo](int signum) { /* use foo here */ }); 

Si potrebbe effettivamente mantenere sockfd1 e sockfd2 come variabili globali e poi, li si potrebbe utilizzare nel lambda funzione. Ma chiaramente non è un buon progetto. Quindi è meglio usare un design RAII. E se il programma è terminato, le prese saranno comunque chiuse (come segnala @Dani).

0

Le prese saranno sempre chiuse quando un programma è chiuso, non c'è bisogno di preoccuparsene.
Se ti preoccupi per la gestione delle risorse logiche, metterlo in distruttori, ma quelli non sarà chiamato quando l'utente preme CTRL-C

1

Un po 'in ritardo, ma se qualcuno ha bisogno di una soluzione del genere si può usare std::function come un wrapper per contenere un lambda in grado di catturare variabili:

#include <functional> 
#include <iostream> 

namespace { 
std::function<void(int)> shutdown_handler; 
void signal_handler(int signal) { shutdown_handler(signal); } 
} // namespace 

int main(int argc, char *argv[]) { 
    std::signal(SIGINT, signal_handler); 
    MyTCPServer server; 
    shutdown_handler = [&](int signal) { 
    std::cout << "Server shutdown...\n"; 
    server.shutdown(); 
    }; 
    server.do_work_for_ever(); 
} 
Problemi correlati