My method that uses multithreading is:
typedef std::pair<std::vector<char>, int> PATH_PAIR;
std::list<PATH_PAIR>
TSP::return_all_paths_list(
PATH_PAIR parent_path_pair,
std::list<char> unvisited_cities
) {
std::list<PATH_PAIR> subseq_paths_list;
std::vector<std::future<std::list<PATH_PAIR>>> future_vec;
if (unvisited_cities.empty()) { // END RECURSION
// NON-REALTED CODE
return subseq_paths_list;
}
for (const char curr_city: unvisited_cities) { // DO RECURSION
PATH_PAIR new_path_pair_addr = parent_path_pair;
std::list<char> subseq_unvisited_cities = unvisited_cities;
std::future<std::list<PATH_PAIR>> returned_path_list_future;
// NON-RELATED CODE
returned_path_list_future = std::move(std::async(std::launch::async, return_all_paths_list, this, new_path_pair_addr, subseq_unvisited_cities));
future_vec.push_back(returned_path_list_future);
}
while (!future_vec.empty()) { // GET-VALUES-WHILE
for (std::future<std::list<PATH_PAIR>>& curr_future : future_vec) // GET-VALUES-FOR
if (curr_future.valid()) {
subseq_paths_list.merge(curr_future.get());
}
// future_list.remove_if(
// [] (std::future<std::list<PATH_PAIR>> input_future) -> bool {
// return !input_future.valid();
// }
// );
}
return subseq_paths_list;
}
I have a few questions:
-
As per cppreference std::async:
If the std::future obtained from std::async is not moved from or bound to a reference, the destructor of the std::future will block at the end of the full expression until the asynchronous operation completes, essentially making code such as the following synchronous:
std::async(std::launch::async, []{ f(); }); // temporary's dtor waits for f() std::async(std::launch::async, []{ g(); }); // does not start until f() completesa. What do the words "move from" and "bound to a reference" mean?
b. Will wrapping the call tostd::asyncinside anstd::movemake the calls tostd::asyncnot block in the suceeding iterations of// DO RECURSIONloop?
c. Or are the calls in the above two lines blocking just because lambdas are used? -
How do I check if a shared state is ready?
a. A call tostd::future::wait(andstd::future::get) blocks until the shared state is ready. The thing is, I don't want to wait. I want to check if a shared state is ready, if it's not, I want to move on to the nextstd::futureobject. How do I do that?std::future::validonly checks if a shared state is associated with an object.
b. Also, again as per cppreference std::async, the return value of a call tostd::asyncis:std::future referring to the shared state created by this call to
std::asyncSo, in the
//GET VALUESloops, thestd::futureobtained will always returntrueifstd::future::validis called on it (providedstd::future::getisn't called on it yet). If I remove anstd::futureafter anstd::future::getis called, I don't have to check the validity of thestd::futureobjects. But, none of the remove element STL methods I've tried don't work, there's compile time errors spanning to about twice the height of my display.I thought, maybe calling
std::future::getalso destroys the object in addition to releasing the shared state, but a small test piece of code I wrote:int mul2(int x) {return x << 1; } int main() { std::vector<std::future<int>> fut_vec; for (int i = 0; i < 5; i++) { fut_vec.push_back(std::move(std::async(std::launch::async, mul2, i))); } for (std::vector<std::future<int>>::iterator itr = fut_vec.begin(); itr != fut_vec.end(); itr++) { if (itr->valid()) { std::cout << "Value: " << itr->get() << " | No. of vec elements(futures): " << fut_vec.size() << std::endl; } } return 0; }reveals the
fut_vec.size()always returns the same integer.How do I destroy an
std::futureobject?
I recently got into multithreading, so now I'm trying to implement the travelling salesman problem using multithreading.
Aucun commentaire:
Enregistrer un commentaire