There you are designing a parallel algorithm, and then it occurs to you: How do I return information to the main thread from a child thread?
If you’ve skimmed through half of The C++ Programming Language (4th Edition) by Bjarne Stroustrup like I have, you may recall a section about futures and promises which are related to threads.
Well those are exactly what we need, although I am sure you could create a custom solution. Like perhaps locking and inserting your data into an external container. Perhaps you prefer a standard C++ answer to your problems though? This way it makes sense and you need less comments.
My case was that I wished to learn the “proper” way to do it, and boy did I have a time learning.
Let’s get to the bottom line.. std::promise and std::future are the “proper” way to extract processed data from a thread. So how does one do that?
Well here is an excerpt from my WordSearch project.
struct ThreadResults //Might as well package these together
{
std::future<std::vector<FoundWord>> future;
std::promise<std::vector<FoundWord>> promise;
};
using std::thread;
using Task = std::pair < thread*, ThreadResults* >; //This is practically a comment already
std::vector<Task> Task_List;
//We need threads to extract from
for ( auto search_word_list : Search_Words )
{ //Our Puzzle Words are grouped by size
for ( int i = search_word_list.first; i <= largest_search_area; ++i )
{ //search_word_list.first is the size of words in the list
//We only want search areas big enough for the word to fit in
if ( Search_Areas.find( i ) != Search_Areas.end() )
{
std::vector<WordBoxWord>& search_area_list = Search_Areas[i];
ThreadResults* shared_state = new ThreadResults;
//You need to associate the promise to the future. That is why promise::get_future() exists
shared_state->future = shared_state->promise.get_future();
//This is the part that got me. You need to std::move( promise ) in order to pass it to a new thread.
//I tried passing by reference. Pointer.. you name it. This is how you do it!
std::thread *T = new std::thread( SearchAlg, std::move( shared_state->promise ), search_word_list.second, std::ref( search_area_list ) );
Task_List.push_back( std::make_pair( T, shared_state ) );
}
}
}
//While there are tasks we haven't checked on
while ( Task_List.size() != 0 )
{
auto task = Task_List.begin();
task->first->join(); // These are threads we're dealing with.. gotta join them back
auto results = task->second->future.get(); // EXTRACTION!! WOO
for ( auto word_iterator = results.begin(); word_iterator != results.end(); ++word_iterator )
{
this->Words_Found.push_back( *word_iterator );
}
delete task->first;// thread
delete task->second; // data
//Task data is saved and pointers deleted, erase the task
Task_List.erase( task );
}