c++xcodec++11packaged-task

C++11 packaged_task running with its own thread need a join() in order to get future


From the C++11 book I recently got, I am trying to build the example on page 123 (packaged_task 5.3.5.2) and after a few things to make this work with XCode, I have a couple of questions:

First, there seems to be a requirement to pass a function pointer to the packaged_task ctor. The text doesn't show the ampersand, so maybe it's a typo or a late standard change?

Then, and more important, I had to add thread.join(s) to be able to call get and avoid getting a sigabrt and the process exits without printing anything. I was under the impression that a call to get future would block till the thread returns a value, but this doesn't seem to be the case. Adding the join also seem to defy the asynchronous (non-blocking) nature of the code. Why can't get on the future do the join itself if it needs to? Reading from the docs, it says that a get will call implicitly wait and even by adding wait in the code, this still causes a sigabrt. This is very puzzling.

I am using c language dialect c11, -std=gnu++11 and libc++ (with c++11 support). I tried other options with no luck (when using gnuc++, it can't find ). This seems to be the only combinations I can use to build the code. XCode is very picky about what it needs to compile c++11.

Thanks for your help in advance.

Here is the test case from the book with my 'fixes' to make the code run:

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

Solution

  • You need to either detach or join every thread object before destroying it. If you're using futures I'd expect the threads to have significantly longer lifetimes than the futures.