Reputation: 4523
If I want to get the result from a thread, which of the following code is correct? Or there exists better way to achieve the same goal?
void foo(int &result) {
result = 123;
}
int bar() {
return 123;
}
int main() {
int foo_result;
std::thread t1(foo, std::ref(foo_result));
t1.join();
std::future<int> t2 = std::async(bar);
int bar_result = t2.get();
}
And another case,
void baz(int beg, int end, vector<int> &a) {
for (int idx = beg; idx != end; ++idx) a[idx] = idx;
}
int main() {
vector<int> a(30);
thread t0(baz, 0, 10, ref(a));
thread t1(baz, 10, 20, ref(a));
thread t2(baz, 20, 30, ref(a));
t0.join();
t1.join();
t2.join();
for (auto x : a) cout << x << endl;
}
Upvotes: 2
Views: 225
Reputation: 17708
The second one is simpler, better and safer.
With the first one, you are sharing an object, bar
, between the two threads. You clearly need to enforce some form of synchronization or policy in order to safely use the result object.
Another issue with the first one is that the lifetime of the referenced result object is tied to the lifetime of the original object which, in your case, is in the initiating thread. This might be very unsafe if the referred-to object leaves out of scope with the worker thread still unfinished doing its job, and has still not written to the result object.
The second one is much better as it address the two issues above. You can also use it on any function that returns its result without that function knowing it is being concurrently executed. Of course you still need be careful not to introduce data races and undefined behavior when sharing data, especially with global variables.
To be honest, I think your second example is a bit contrived. You typically don't want to use separate threads in doing such a trivial task. With that, you are exposing yourself into a data race. Even if you do synchronize their access, the overhead of initiating a thread and synchronization would put it at a serious disadvantage against single threaded code.
Upvotes: 1
Reputation: 22519
In C++11, you want to use std::future
From this documentation link:
The class template std::future provides a mechanism to access the result of asynchronous operations
And some sample code, also from that link, to illustrate its use.
#include <iostream>
#include <future>
#include <thread>
int main()
{
// future from a packaged_task
std::packaged_task<int()> task([](){ return 7; }); // wrap the function
std::future<int> f1 = task.get_future(); // get a future
std::thread(std::move(task)).detach(); // launch on a thread
// future from an async()
std::future<int> f2 = std::async(std::launch::async, [](){ return 8; });
// future from a promise
std::promise<int> p;
std::future<int> f3 = p.get_future();
std::thread( [](std::promise<int>& p){ p.set_value(9); },
std::ref(p) ).detach();
std::cout << "Waiting..." << std::flush;
f1.wait();
f2.wait();
f3.wait();
std::cout << "Done!\nResults are: "
<< f1.get() << ' ' << f2.get() << ' ' << f3.get() << '\n';
}
Upvotes: 2
Reputation: 1628
There are many ways.
See the example code at the bottom of http://en.cppreference.com/w/cpp/thread/future
Upvotes: 2