使用boost :: lambda :: bind进行任意函数调用?

时间:2012-01-24 18:42:19

标签: c++ boost lambda bind

我必须使用extern库提供许多免费功能,可以完成大量的网络工作。遗憾的是,这个库并不是非常安全的,它恰好会永远陷入某些功能(或者至少很长一段时间)。这对我来说不是一个选项,所以如果花费的时间太长,我想打断电话。

看一下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传递给我的函数吗?

更新

根据建议,我尝试使用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的函数签名是不是boost::packaged_task?我做错了什么?

更新2:

我终于得到了它的工作,但我不知道我在做什么是一个很好的方法,因为我发现在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"); } 找到任何文档或示例非常困难,基本上我都是与之合作的是图书馆的source code。这是我的工作职能:

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;
}

我对它并不完全满意,主要是因为它不适用于临时工,意味着你必须这样使用它:

{{1}}

如果对这些结构更擅长的人能对此发表评论,我仍然会感到非常高兴。

1 个答案:

答案 0 :(得分:1)

这会有用吗?

template <class T, class F>
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");
}