1

从我最近得到的 C++11 书中,我正在尝试在第 123 页(packaged_task 5.3.5.2)上构建示例,经过一些事情以使其与 XCode 一起工作,我有几个问题:

首先,似乎需要将函数指针传递给 packaged_task ctor。文本没有显示 & 符号,所以可能是拼写错误或标准更改较晚?

然后,更重要的是,我必须添加 thread.join(s) 才能调用 get 并避免获得 sigabrt 并且进程退出而不打印任何内容。我的印象是调用获取未来会阻塞,直到线程返回一个值,但情况似乎并非如此。添加连接似乎也违背了代码的异步(非阻塞)性质。如果需要,为什么不能加入未来呢?从文档中读取,它说 get 将隐式调用等待,即使在代码中添加等待,这仍然会导致 sigabrt。这是非常令人费解的。

我正在使用 c 语言方言 c11、-std=gnu++11 和 libc++(支持 c++11)。我尝试了其他没有运气的选项(使用 gnuc++ 时,它找不到)。这似乎是我可以用来构建代码的唯一组合。XCode 对编译 c++11 所需的内容非常挑剔。

提前感谢您的帮助。

这是书中的测试用例,其中包含我的“修复”以使代码运行:

    #include <iostream>
    #include <numeric>
    #include <vector>
    #include <thread>
    #include <future>

    using namespace std;

    double accum(double *beg, double *end, double init)
    {
        return accumulate(beg, end, init);
    }

    double comp2(vector<double>& v)
    {

        using Task_type = double(double*,double*,double);

        packaged_task<Task_type> pt0 {&accum}; //use '&' to compile
        packaged_task<Task_type> pt1 {&accum}; //use '&' to compile

        future<double> f0 {pt0.get_future()};
        future<double> f1 {pt1.get_future()};

        double* first=&v[0];
        thread t1 {move(pt0), first, first+v.size()/2, 0};
        thread t2 {move(pt1), first+v.size()/2, first+v.size(), 0};

        // need this to run
        t1.join(); 
        t2.join();

        // using this instead of the join doesn't work
//      f0.wait(); 
//      f1.wait();

        return f0.get() + f1.get();
    }

    int main()
    {
        vector<double> v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        cout<<comp2(v)<<endl;
        return 0;
    }
4

3 回答 3

1

在销毁它之前,您需要分离或加入每个线程对象。如果您使用期货,我希望线程的寿命比期货长得多。

于 2013-11-30T22:58:20.253 回答
0

您需要在线程上调用 join() ,否则将其分离。是这个问题吗?在这种情况下,packaged_task 可用于异常安全,但您仍然有一对运行该节目的线程。

于 2013-11-30T23:13:10.413 回答
0

我认为当前的答案并没有直接回答这个问题。您不需要显式创建线程来运行任务。例如:

#include <future>
#include <stdexcept>
#include <iostream>
#include <thread>
#include <utility>
#include <functional>

using namespace std;

int ff(int i)
{
  return i;
}

int main(int argc, char *argv[])
{

  packaged_task<int(int)> pt1 (ff);
  auto v1 = pt1.get_future();
  thread t1(move(pt1), 1);
  t1.join();

  packaged_task<int(int)> pt2(ff);
  auto v2 = pt2.get_future();
  pt2(1);
  cout << v2.get() << endl;

  return 0;
}

如果你编译上面的例子,你会看到 1 作为标准输出。

但令我困惑的是,如果我注释掉第一个 packaged_task,然后我看到一个std::system_error,完整的代码是:

#include <future>
#include <stdexcept>
#include <iostream>
#include <thread>
#include <utility>
#include <functional>

using namespace std;

int ff(int i)
{
  return i;
}

int main(int argc, char *argv[])
{

  // packaged_task<int(int)> pt1 (ff);
  // auto v1 = pt1.get_future();
  // thread t1(move(pt1), 1);
  // t1.join();

  packaged_task<int(int)> pt2(ff);
  auto v2 = pt2.get_future();
  pt2(1);
  cout << v2.get() << endl;

  return 0;
}

显然这两个 packaged_tasks 是独立的,但删除第一个会导致第二个失败并带有system_error.

这不是对问题的回答,而是试图澄清问题。

于 2017-12-06T20:39:31.837 回答