简体   繁体   中英

Error about std::promise in C++

I am trying to pass my class instance into threads and the return the processed objects from threads. I've googled about C++ multithreading, and found that std::promising can be helpful.

However, I am stuck at the very beginning. Here is my code:

void callerFunc()
{
    //...
    std::promise<DataWareHouse> data_chunks;    
    // DataWareHouse is my customized class
    //data_chunks has a vector<vector<double>> member variable
    std::thread(&run_thread,data_chunks);
    // ............
}

void run_thread(std::promise<DataWareHouse> data_chunks)
{
    // ... 
    vector<vector<double>> results;
    // ...
    data_chunks.set_value(results);
}

The above code generates an error:

 `error C2248: 'std::promise<_Ty>::promise' : cannot access private member declared in class 'std::promise<_Ty>'`

May I know what am I wrong and how to fix it?

Many thanks. :-)

Your first problem is that you are using std::thread -- std::thread is a low level class which you should build higher abstractions up on. Threading is newly standardized in C++ in C++11, and all of the rough parts are not filed off yet.

There are three different patterns for using threading in C++11 that might be useful to you.

First, std::async . Second, std::thread mixed with std::packaged_task . And third, dealing with std::thread and std::promise in the raw.

I'll illustrate the third, which is the lowest level and most dangerous, because that is what you asked for. I would advise looking at the first two options.

#include <future>
#include <vector>
#include <iostream>

typedef std::vector<double> DataWareHouse;

void run_thread(std::promise<DataWareHouse> data_chunks)
{
  DataWareHouse results;
  results.push_back( 3.14159 );
  data_chunks.set_value(results);
}

std::future<DataWareHouse> do_async_work()
{
  std::promise<DataWareHouse> data_chunks;  
  std::future<DataWareHouse> retval = data_chunks.get_future();
  // DataWareHouse is my customized class
  //data_chunks has a vector<vector<double>> member variable
  std::thread t = std::thread(&run_thread,std::move(data_chunks));
  t.detach(); // do this or seg fault
  return retval;
}

int main() {
  std::future<DataWareHouse> result = do_async_work();
  DataWareHouse vec = result.get(); // block and get the data
  for (double d: vec) {
    std::cout << d << "\n";
  }
}

Live example

With std::async , you'd have a function returning DataWareHouse , and it would return a std::future<DataWareHouse> directly.

With std::packaged_task<> , it would take your run_thread and turn it into a packaged_task that can be executed, and a std::future extracted from it.

std::promise<> is not copyable, and in calling run_thread() you are implicitly trying to invoke the copy constructor. The error message is telling you that you cannot use the copy constructor since it is marked private.

You need to pass a promise by reference ( std::promise<DataWareHouse> & ). This is safe if callerFunc() is guaranteed not to return until run_thread() is finished with the object (otherwise you will be using a reference to a destroyed stack-allocated object, and I don't have to explain why that's bad).

You're trying to pass the promise to the thread by value; but you need to pass by reference to get the results back to the caller's promise. std::promise is uncopyable, to prevent this mistake.

std::thread(&run_thread,std::ref(data_chunks));
                        ^^^^^^^^

void run_thread(std::promise<DataWareHouse> & data_chunks)
                                            ^

The error is telling you you cannot copy an std::promise , which you do here:

void run_thread(std::promise<DataWareHouse> data_chunks)

and here:

std::thread(&run_thread,data_chunks); // makes copy of data_chunks

You should pass a reference:

void run_thread(std::promise<DataWareHouse>& data_chunks);
//                                         ^

And then pass an std::reference_wrapper to the thread, otherwise it too will attempt to copy the promise. This is easily done with std::ref :

std::thread(&run_thread, std::ref(data_chunks));
//                       ^^^^^^^^

Obviously data_chunks must be alive until the thread finished running, so you will have to join the thread in callerFunc() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM