Reputation: 113
I am working with threads for the first time in C++ and I would like to know what is wrong with my code.
I am working on Boruvka`s algorithm and I would like to make threads for finding the shortest Edge for component.
Here is my code:
std::vector<std::thread> threads;
std::vector<Edge> minEdges;
for (auto g: components) {
Edge minEd;
minEdges.push_back(minEd);
threads.push_back(std::thread (findPath, g, std::ref(minEdges.back())));
}
for (auto &i : threads) {
i.join();
}
for (Edge edge:minEdges) {
if (!contains(mst, edge)) {
addEdge(&mst, edge.n1, edge.n2, edge.weight);
}
}
void findPath(Graph &component, Edge &edge)
//finds cheapest edge
For exlanation, I would like to give the component and a reference to an element in minEdges
where will be stored the cheapest edge. Then I want to join all the threads and put all minimum edges to the mst.
This code gives me an error on line, where I`m pushing threads to the vector, but I could not find why. So can you please tell me?
Error message(i just deleted paths to the files):
In instantiation of 'struct std::_Bind_simple<void (*(Graph, std::reference_wrapper<Edge>))(Graph&, Edge&)>':
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/thread:142:59:
required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(Graph&, Edge&); _Args = {Graph&, std::reference_wrapper<Edge>}]'
graph.cpp:232:82: required from here
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/functional:1505:61: error: no type named 'type' in 'class std::result_of<void (*(Graph, std::reference_wrapper<Edge>))(Graph&, Edge&)>'
typedef typename result_of<_Callable(_Args...)>::type result_type;
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/functional:1526:9: error: no type named 'type' in 'class std::result_of<void (*(Graph, std::reference_wrapper<Edge>))(Graph&, Edge&)>'
_M_invoke(_Index_tuple<_Indices...>)
^
^
Thank you for the answers.
Upvotes: 2
Views: 2756
Reputation: 85541
A few points...
Don't modify vectors which are already in use by other threads (adding to a vector can move other elements)
Iterate over references, not temporaries (auto g
)
Prefer emplace_back
whenever possible
Optionally try the lambda syntax
Use synchronization to be sure things happen in the order you think they would (not needed in your case - thread creation acts as a memory fence)
std::vector<Edge> minEdges;
for (auto &g: components) {
minEdges.emplace_back();
}
std::vector<std::thread> threads;
for (size_t i=0; i<components.size(); ++i) {
threads.emplace_back([&]{findPath(components[i], minEdges[i]);});
}
// rest of code...
Upvotes: 1