为什么我可以多次调用boost :: unique_future :: get,与std :: future不同?

时间:2014-03-16 05:10:28

标签: c++ boost boost-thread

我知道我们无法多次致电std::future::get,如果我们需要多次致电,我们应该使用std::shared_future

但我们可以多次拨打boost::unique_future::get,但有boost::shared_future

void test1()
{
    int i, j;

    std::future<int> fu1 = std::async([]{ return 42; });
    i = fu1.get();
    //j = fu1.get(); // error occur
    std::cout << i << std::endl;

    boost::unique_future<int> fu2 = boost::async([]{ return 43; });
    i = fu2.get();
    j = fu2.get(); // sucess...?
    std::cout << i << ' ' << j << std::endl;

    std::cin.get();
}

输出结果为:

42
43 43

我想了一会然后试试这个测试代码。

class TestCls
{
public:
    TestCls()
    {
        std::cout << "[TestCls] default constructor" << std::endl;
    }
    TestCls(const TestCls &other)
    {
        std::cout << "[TestCls] copy constructor" << std::endl;
    }
    TestCls(TestCls &&other)
    {
        std::cout << "[TestCls] move constructor" << std::endl;
    }
    TestCls &operator =(const TestCls &other)
    {
        std::cout << "[TestCls] copy assignment" << std::endl;
        return *this;
    }
    TestCls &operator =(TestCls &&other)
    {
        std::cout << "[TestCls] move assignment" << std::endl;
        return *this;
    }
};
void test2()
{
    TestCls a, b;

    std::cout << std::endl << "unique_future test begin" << std::endl;
    boost::unique_future<TestCls> fu1 = boost::async([]{ return TestCls(); });
    fu1.wait();
    std::cout << "first assignment" << std::endl;
    a = fu1.get();
    std::cout << "second assignment" << std::endl;
    b = fu1.get();
    std::cout << "unique_future test end" << std::endl;

    std::cout << std::endl << "shared_future test begin" << std::endl;
    boost::shared_future<TestCls> fu2 = boost::async([]{ return TestCls(); });
    fu2.wait();
    std::cout << "first assignment" << std::endl;
    a = fu2.get();
    std::cout << "second assignment" << std::endl;
    b = fu2.get();
    std::cout << "shared_future test end" << std::endl;

    std::cin.get();
}

输出结果为:

[TestCls] default constructor
[TestCls] default constructor

unique_future test begin
[TestCls] default constructor
[TestCls] move constructor
first assignment
[TestCls] move constructor
[TestCls] move assignment
second assignment
[TestCls] move constructor
[TestCls] move assignment
unique_future test end

shared_future test begin
[TestCls] default constructor
[TestCls] move constructor
first assignment
[TestCls] copy assignment
second assignment
[TestCls] copy assignment
shared_future test end

虽然boost::unique_future执行“移动”,而不是“复制”,但允许多次调用get ..怎么可能?

(我的升级版本是1.55.0,我的编译器是VC ++ 2013)


如果我#define BOOST_THREAD_VERSION 4,则get()的第二次调用会发生异常。多次调用get()是未定义的行为,直到版本3?或者它被允许到版本3?

1 个答案:

答案 0 :(得分:0)

the documentation可以清楚地知道至少有3个宏在你正在使用的东西中发挥重要作用

BOOST_THREAD_VERSION

设置了库的版本,即使4到3之间有重大变化,你似乎也没有问题。

第二个宏是BOOST_THREAD_PROVIDES_FUTURE,这个宏是一个开关,没有附加值,如果定义它会启用&#34;标准&#34;你可以调用的unique_future只是一个占位符,可以在编译时由这个宏定义。

来自文件boost/thread/future.hpp

#if defined BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_FUTURE future
#else
#define BOOST_THREAD_FUTURE unique_future
#endif
文件boost/thread/detail/config.hpp中的

您还有BOOST_THREAD_DONT_PROVIDE_FUTURE,这是默认操作的另一个开关

// PROVIDE_FUTURE
#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE \
 && ! defined BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE
#endif

请注意否定!,这意味着如果您定义BOOST_THREAD_DONT_PROVIDE_FUTURE,您应该得到&#34;真实&#34; unique_future由图书馆记录。

您基本上是在获取默认行为,而且您使用库的第4版这一事实并不重要。

关于C ++ 11及更高版本的附注:

std::async([]{ return 42; });

这是C ++ 11中的不良做法及其在C ++ 14中的未定义行为,您应始终为async指定启动策略。