【问题标题】:Arbitrary function call with boost::lambda::bind?使用 boost::lambda::bind 的任意函数调用?
【发布时间】:2012-01-24 18:42:19
【问题描述】:

我必须使用一个 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::binds 传递给我的函数吗?

更新:

按照建议,我尝试使用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&lt;int&gt;(boost::packaged_task&lt;int&gt;(boost::bind(&amp;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)’

除了int 将被隐式转换的部分之外,timeout(boost::packaged_task&lt;int&gt;, int) 不正是我的timeout 函数签名吗?我做错了什么?

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

如果有更熟悉这些结构的人对此发表评论,我仍然会非常高兴。

【问题讨论】:

  • 为什么不直接使用boost::packaged_task
  • @Mankarse 老实说,因为我从未听说过。我会调查一下。谢谢。
  • @Mankarse 让它与 boost::packaged_task 一起工作。谢谢!
  • PS:也许将您的评论推广到答案,以便我可以为您提供信用?

标签: c++ boost lambda bind


【解决方案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");
}

【讨论】:

  • 我该如何调用这个函数?
  • 如果函数超时,行为未定义。线程将继续运行,并最终尝试在ret 中存储一个值,但在控制离开timeout 后,对ret 的引用将不再有效。
  • @Rob Kennedy 是的,在else 的情况下线程应该被中断。谢谢。
  • 你称它为 yiu 在示例中的名称。 F类型会自动解析。只需确保您的绑定对象可以是 const 或可以复制。
  • 天哪,有时我真的看不到眼前的解决方案。感谢您的帮助,它运行良好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-11
  • 2011-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多