Мне нужно использовать внешнюю библиотеку, предоставляющую множество бесплатных функций, которые делают много сетевых материалов. К сожалению, эта библиотека не очень надежна, и это случается, чтобы застрять в некоторых из этих функций навсегда (или, по крайней мере, очень долгое время). Это не вариант для меня, поэтому я хочу прервать вызов, если он слишком долго.Произвольный вызов функции с boost :: lambda :: bind?
Взглянув на C++: How to implement a timeout for an arbitrary function call? и boost::lambda
библиотеку, я пришел с этим:
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
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<int>(&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;
}
компилируется и работает как шарм. Однако проблема заключается в том, что у меня есть много функций с разными параметрами и возвращаемыми значениями, и для написания вышеизложенного для каждого случая кажется утомительной и избыточной работой для меня. Поэтому я хочу, чтобы обернуть его в функции:
template <class t> t timeout(bindparam<t> &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");
}
Идея заключается в том, что я могу запустить критическую функцию с
try {
int ret = timeout<int>(boost::lambda::bind<int>(&foo, 1, 2), 500);
std::cout << ret << std::endl;
}
catch(std::runtime_error &e) {
std::cerr << e.what() << std::endl;
}
, но я понятия не имею, как это сделать, или является ли он даже возможное. Могу ли я передать произвольно boost::lambda::bind
s моей функции?
Update:
Как было предложено, я попробовал с boost::packaged_task
:
template <class T> T timeout(boost::packaged_task<T> &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");
}
}
Но когда я пытаюсь использовать его как timeout<int>(boost::packaged_task<int>(boost::bind(&foo, 1, 2)), 500);
я получаю странную ошибку компилятора:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:35: error: no matching function for call to ‘timeout(boost::packaged_task<int>, int)’
Это не timeout(boost::packaged_task<int>, int)
в значительной степени точно моя подпись функции timeout
, за исключением части int
, которая будет преобразована неявно? Что я делаю не так?
Update 2:
я, наконец, получил его на работу, но я понятия не имею ли то, что я делаю, это хороший способ сделать это, потому что я нашел, что это невероятно трудно найти какую-либо документацию или примеры на boost::packaged_task
и в основном все, с чем я работал, это source code библиотеки. Вот моя рабочая функция:
template <class T> T timeout(boost::packaged_task<T> &f, long sleep) {
boost::thread thrd(boost::lambda::bind(&boost::packaged_task<T>::operator(), &f));
if(thrd.timed_join(boost::posix_time::milliseconds(sleep))) {
boost::unique_future<T> ret = f.get_future();
return ret.get();
}
thrd.interrupt();
throw std::runtime_error("timeout");
}
Я не полностью счастлива с ним, в основном потому, что он не работает с временных, то есть вы должны пройти этот путь, чтобы использовать его:
try {
boost::packaged_task<int> f(boost::lambda::bind(&foo, 1, 2));
int sum = timeout<int>(f, 500);
std::cout << sum << std::endl;
}
catch(std::runtime_error &e) {
std::cerr << e.what() << std::endl;
}
I Would все еще очень рад, если кто-то, кто разбирается в этих структурах, может прокомментировать это.
Почему бы просто не использовать 'boost :: packaged_task'? – Mankarse
@Mankarse Честно говоря, потому что я никогда не слышал об этом. Я рассмотрю его. Благодарю. – nijansen
@Mankarse Получил его для работы с boost :: packaged_task. Благодаря! – nijansen