Appel de fonction arbitraire avec boost :: lambda :: bind?

Je dois utiliser une bibliothèque externe offrant de nombreuses fonctions gratuites, qui permettent de nombreuses tâches de mise en réseau. Malheureusement, cette bibliothèque n’est pas très sécurisée et rest bloquée dans certaines de ces fonctions pour toujours (ou du moins très longtemps). Ce n’est pas une option pour moi, donc je veux interrompre l’appel si cela prend trop de temps.

Jetons un coup d’œil à C ++: comment implémenter un délai d’attente pour un appel de fonction arbitraire? et le boost::lambda librairie boost::lambda , je suis venu avec ceci:

 #include  #include  #include  #include  int foo(int a, int b) { boost::this_thread::sleep(boost::posix_time::seconds(2)); return a+b; } int main() { int ret; boost::thread thrd(boost::lambda::var(ret) = boost::lambda::bind(&foo, 1, 2)); if(thrd.timed_join(boost::posix_time::seconds(1))) { std::cout << ret << std::endl; } else { std::cerr << "Function timed out." << std::endl; } return 0; } 

Comstack et fonctionne à merveille. Cependant, le problème est que j’ai beaucoup de fonctions avec différents parameters et valeurs de retour, et écrire ce qui précède pour chaque cas me semble être un travail fastidieux et redondant. Donc, je veux l’envelopper dans une fonction:

 template  t timeout(bindparam &bind /* read below */, long sleep) { t ret; boost::thread thrd(boost::lambda::var(ret) = bind); if(thrd.timed_join(boost::posix_time::milliseconds(sleep))) { return ret; } else throw std::runtime_error("timeout"); } 

L’idée est que je puisse exécuter la fonction critique avec

 try { int ret = timeout(boost::lambda::bind(&foo, 1, 2), 500); std::cout << ret << std::endl; } catch(std::runtime_error &e) { std::cerr << e.what() << std::endl; } 

mais je ne sais pas comment faire cela, ni même si c’est possible. Puis-je passer boost::lambda::bind s de façon arbitraire à ma fonction?

Mettre à jour:

Comme suggéré, je l’ai essayé avec boost::packaged_task :

 template  T timeout(boost::packaged_task &f, long sleep) { T ret; boost::thread thrd(boost::lambda::var(ret) = f); if(thrd.timed_join(boost::posix_time::milliseconds(sleep))) { return ret; } else { thrd.interrupt(); throw std::runtime_error("timeout"); } } 

Mais lorsque j’essaie de l’utiliser comme timeout(boost::packaged_task(boost::bind(&foo, 1, 2)), 500); d’ timeout(boost::packaged_task(boost::bind(&foo, 1, 2)), 500); Je reçois une erreur de compilation étrange:

 main.cpp: In function 'int main(int, char**)': main.cpp:35: error: no matching function for call to 'timeout(boost::packaged_task, int)' 

timeout(boost::packaged_task, int) n’est-il pas exactement la signature de fonction de timeout , à l’exception de la partie int qui sera convertie implicitement? Qu’est-ce que je fais mal?

Mise à jour 2:

Je me suis finalement mis au travail, mais je ne sais pas si ce que je fais est un bon moyen de le faire, car j’ai trouvé extrêmement difficile de trouver de la documentation ou des exemples sur boost::packaged_task et, fondamentalement, j’ai travaillé avec code source de la bibliothèque. Voici ma fonction de travail:

 template  T timeout(boost::packaged_task &f, long sleep) { boost::thread thrd(boost::lambda::bind(&boost::packaged_task::operator(), &f)); if(thrd.timed_join(boost::posix_time::milliseconds(sleep))) { boost::unique_future ret = f.get_future(); return ret.get(); } thrd.interrupt(); throw std::runtime_error("timeout"); } 

Je ne suis pas complètement satisfait de cela, principalement parce que cela ne fonctionne pas avec les temporaires, ce qui signifie que vous devez utiliser cette méthode pour l’utiliser:

 try { boost::packaged_task f(boost::lambda::bind(&foo, 1, 2)); int sum = timeout(f, 500); std::cout << sum << std::endl; } catch(std::runtime_error &e) { std::cerr << e.what() << std::endl; } 

Je serais toujours très heureux si quelqu’un de plus habile avec ces structures pouvait commenter à ce sujet.

cela fonctionnerait-il?

 template  T timeout(const F &bind, long sleep) { T ret; boost::thread thrd(boost::lambda::var(ret) = bind); if(thrd.timed_join(boost::posix_time::milliseconds(sleep))) { return ret; } else throw std::runtime_error("timeout"); }