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() completes
a. What do the words "move from" and "bound to a reference" mean?
b. Will wrapping the call tostd::async
inside anstd::move
make the calls tostd::async
not block in the suceeding iterations of// DO RECURSION
loop?
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::future
object. How do I do that?std::future::valid
only 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::async
is:std::future referring to the shared state created by this call to
std::async
So, in the
//GET VALUES
loops, thestd::future
obtained will always returntrue
ifstd::future::valid
is called on it (providedstd::future::get
isn't called on it yet). If I remove anstd::future
after anstd::future::get
is called, I don't have to check the validity of thestd::future
objects. 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::get
also 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::future
object?
I recently got into multithreading, so now I'm trying to implement the travelling salesman problem using multithreading.
Aucun commentaire:
Enregistrer un commentaire