With win32 threads I have the straight forward GetExitCodeThread()
that gives me the value which the thread function returned. I'm looking for something similar for std::thread
(or boost threads)
As I understand this can be done with futures but how exactly?

- 76,898
- 55
- 205
- 325
8 Answers
See this video tutorial on C++11 futures.
Explicitly with threads and futures:
#include <thread>
#include <future>
void func(std::promise<int> && p) {
p.set_value(1);
}
std::promise<int> p;
auto f = p.get_future();
std::thread t(&func, std::move(p));
t.join();
int i = f.get();
Or with std::async
(higher-level wrapper for threads and futures):
#include <thread>
#include <future>
int func() { return 1; }
std::future<int> ret = std::async(&func);
int i = ret.get();
I can't comment whether it works on all platforms (it seems to work on Linux, but doesn't build for me on Mac OSX with GCC 4.6.1).

- 82,554
- 44
- 203
- 280
-
AlexB. Wouldn't that terminate with std::system_error (see http://ideone.com/36Qkn), or is that a limitation of IdeOne? I was just typing that as my own answer was sidetracked by the exception :) – sehe Oct 07 '11 at 12:16
-
2@sehe Usually these sandboxed environments do not allow threads to be started. – Alex B Oct 07 '11 at 12:18
-
@sehe In all likeliness this is on a Linux box and compiled without `-pthread`. – Luc Danton Oct 07 '11 at 12:26
-
GCC 4.6 doesn't support std::thread on OS X. std::thread is supported on OS X with clang++ and libc++. – bames53 Oct 26 '11 at 20:43
-
@Alex B could not find the video tutorial, would appreciate if you could upload it somewhere if you have it. thanks in advance. – shivshnkr Oct 27 '13 at 09:22
-
1For `func()` signature, why did you use `&&` instead of `&`? (Also, I notice you carefully call `std::move(p)`, so this appears intentional.) – kevinarpe Oct 03 '16 at 10:31
-
5@kevinarpe [I wrote this 5 years ago and I didn't write any C++ in years, so I'm guessing what past me was trying to do here...] basically promise value is set in another thread. Promise is not copyable, so you can't pass it by value (it doesn't make sense for it to be copyable in the first place). And because stack value can go out of scope, you can't pass it by reference either. So you need to transfer the ownership of the object to the thread = move it + have to pass it as rvalue reference. – Alex B Oct 03 '16 at 12:39
-
[`std::packaged_task`](http://en.cppreference.com/w/cpp/thread/packaged_task) is worth mentioning as it allows you to actually use the *return value* of the thread function instead of having to use a *return parameter*. See the `task_thread()` function of the example in the page I linked. – zett42 Sep 28 '17 at 10:40
-
is there a way to do the same with MinGW, seems like std::future, std::promise, std::thread are missing in it? – Animesh Sahu Jan 22 '21 at 13:18
I'd say:
#include <thread>
#include <future>
int simplefunc(std::string a)
{
return a.size();
}
int main()
{
auto future = std::async(simplefunc, "hello world");
int simple = future.get();
return simple;
}
Note that async even propagates any exceptions thrown from the thread function

- 374,641
- 47
- 450
- 633
-
2
-
1I was forced to use C++ because other languages (at least higher level) just suck at threading... even C#, it's so bad... it's fine if I don't need futures, but if I need both, the input and output of a thread, it gets so complicated that the abstraction it gives just makes no sense... – Boy Jun 27 '18 at 16:30
-
Just check how many questions there are about C# threading, tons... Here is the one with the same question as this one: https://stackoverflow.com/questions/1314155/returning-a-value-from-thread And the answers are so different and bad that makes me wish to never write C# again (besides some win forms I guess XD). New .NET version has async which I guess is imitation of C++ future, but nothing works well... – Boy Jun 27 '18 at 17:46
-
btw, one question, just to be sure, if I add futures to the array, and call get() on each in a loop, will there be a data race? Sry if stupid question, I just don't know how it works under the hood. – Boy Jun 27 '18 at 17:51
-
-
4By the way, the presence of many questions doesn't mean something is badly supported. It mostly means that something is an intrinsic hurdle on the learning curve. Intrinsic complexity is fine, and it SEEMS like surprise if you didn't intuitively expect it. Learning makes the surprise go away. Personally, I think C#'s `Task
` with async+await beats the crap out of C++ language level support (well, for now). I think you're basically seeing programming language evolution upside down. – sehe Jun 27 '18 at 20:42 -
Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/173919/discussion-between-sehe-and-borna). – sehe Jun 27 '18 at 20:43
Using C++11 threads, one can't get the return value as thread exit which used to be the case with pthread_exit(...)
You need to use C++11 Future<>
to get the return value. Future is created using templated argument where the template takes the return value (built in of User Defined types)..
You can fetch the value in another thread using future<..>::get(..)
function.
one benefit of using future<..>
is that you can check the validity of return value i.e if it's already taken, you avoid calling get()
accidentally by checking the validity using future<..>::isValid(...)
function.
Here is how you'll write the code.
#include <iostream>
#include <future>
using namespace std;
auto retFn() {
return 100;
}
int main() {
future<int> fp = async(launch::async, retFn);
if(fp.valid())
cout<<"Return value from async thread is => "<<fp.get()<<endl;
return 0;
}
it should also be noted that we can get the future run on the same thread by using launch::deferred
option as
future<int> fp = async(launch::deferred, retFn);

- 7,554
- 2
- 25
- 36
I think a reference variable reads much more intuitively.
std::mutex m;
void threadFunction(int& val) {
std::lock_guard<std::mutex> guard(m);
val = 5;
}
int x = 0;
std::thread theThread(threadFunction, std::ref(x));
theThread.join();
std::cout << x << std::endl;
// prints 5

- 309
- 2
- 18

- 17,357
- 9
- 82
- 98
-
-
1It would be `theThread` that writes to `x`. This is not seen in the code snippet. – Martin G Jul 14 '18 at 23:09
-
1you are introducing a race condition on x. have to use mutex to lock it not recommended ! – David Dec 19 '18 at 23:14
-
1There is no race condition in the above snippet. The `theThread.join();` blocks and waits for the thread to complete, after which `x` is printed out. – daparic Mar 09 '23 at 09:12
Pass a reference / pointer to the thread with std::ref
async
is just better than this, but just for science, it can be done:
void myfunc_reference(int& i);
std::thread(myfunc_reference, std::ref(output));
I suspect that the implementation of async
must be doing something along those lines under the hood for us, which is essentially what you have to do in the pthread
backend: How to return a value from pthread threads in C?
You have to ensure of course that the variable lifetime lasts until the thread returns.
The following runnable code example compares async and this worse method:
main.cpp
#include <cassert>
#include <future>
#include <iostream>
#include <thread>
#include <vector>
int myfunc(int i) {
return i + 1;
}
void myfunc_reference(int& i) {
i = myfunc(i);
}
int main() {
unsigned int nthreads = 4;
std::vector<int> inputs{1, 2, 3, 4};
std::vector<int> outputs_expect{2, 3, 4, 5};
// future and sync. Nirvana. When you are not fighting to death with types:
// https://stackoverflow.com/questions/10620300/can-stdasync-be-use-with-template-functions
{
std::vector<std::future<int>> futures(nthreads);
std::vector<int> outputs(nthreads);
for (decltype(futures)::size_type i = 0; i < nthreads; ++i) {
futures[i] = std::async(
myfunc,
inputs[i]
);
}
for (decltype(futures)::size_type i = 0; i < nthreads; ++i) {
outputs[i] = futures[i].get();
}
assert(outputs_expect == outputs);
}
// Reference arguments.
//
// Annoying because requires:
//
// - wrapping the return function to accept references
// - keeping an array of outputs
// - std::ref
{
std::vector<std::thread> threads(nthreads);
std::vector<int> inouts(inputs);
for (decltype(threads)::size_type i = 0; i < nthreads; ++i) {
threads[i] = std::thread(myfunc_reference, std::ref(inouts[i]));
}
for (auto& thread : threads) {
thread.join();
}
assert(outputs_expect == inouts);
}
}
Compile and run with:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp -pthread
./main.out
Tested in Ubuntu 19.04.

- 347,512
- 102
- 1,199
- 985
Here is a more specific example.
A function simulates download with a callback parameter to show progress and to cancel the download.
namespace __HeavyWork
{
int SimulateDownload(std::function<int(int)> dlCallBack)
{
for (size_t i = 0; i < 100; i++)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
if (dlCallBack(i) == -1)
{
return i;
}
}
return 100;
}
}
We want to get the download status,
#include <thread>
#include <future>
void test()
{
auto simulateCancellation = []()->bool {
static bool b = true;
if (b)
{
srand((unsigned int)time(NULL));
b = false;
}
return (rand() % 7) == 0;
};
auto funDLCallback = [&](int i)->int {
if (simulateCancellation())
{
return -1;
}
cout << "download: " << i << endl;
return i;
};
auto funDownload = [&](std::promise<int> && p) {
p.set_value(__HeavyWork::SimulateDownload(funDLCallback));
};
std::promise<int> p;
auto f = p.get_future();
std::thread t(funDownload, std::move(p));
//dlg.doModal();
t.join();
cout << "return value: " << f.get() << endl;
}

- 3,030
- 2
- 14
- 31
You can create a set of threads using the code below with threads and futures:
#include <thread>
#include <future>
void func(promise<float> && prms) {
prms.set_value(0.125);
}
in the main:
vector<pair<thread, future<float>>> threads;
for (int i = 0; i < std::thread::hardware_concurrency(); i++) {
promise<float> prms;
future<float> fut = prms.get_future();
///Triggering threads
thread th(func, move(prms));
///Pushing thread and result to vector
threads.push_back(make_pair(move(th), move(fut)));
}
cout<< "Killing threads ... \n";
for (auto& e : threads)
{
auto th = move(e.first);
auto fut = move(e.second);
float flt = fut.get();
//cout << flt << endl;
th.detach();
}

- 1
- 1
It all depends on your definition of "simple".
Using futures will certainly do the magic trick in a few lines of C++, but I find it debatable to hijack a mechanism that was designed for parallel processing for such a trivial use.
futures mostly make sense on multicore CPUS, where they allow a process to launch unsynchronized tasks that will leech computing power from the other cores (leaving aside the fact that finding a set of uncorelated data big enough to be worth the effort is not such a trivial matter either).
Using the whole mechanism as a workaround to retrieve a mere int return value is what I call syntax-driven software design. It sits pretty as a showcase for C++11 versatility, but it does hide considerable resource consumption under an icing of syntactic sugar.
If not for using other cores as raw power source, what is the point in creating a thread if you don't mean to communicate with it until it's done?
Because if you do, retrieving whatever status from it, be it at termination or anytime else, will be a trivial matter and you will not even think of using futures in the first place.
Except for the (arguable) convenience of it or the aesthetic appeal, what do these kinds of tricks achieve functionally that could be considered useful enough to offset the hidden costs?
Reading such answers with no proper multitasking background, the new kids on the block might be tempted by using these kind of inefficient mechanisms on a regular basis.
That would only pollute future software with more cases of Schlemiel the Painter's syndrom.

- 8,479
- 1
- 19
- 43
-
6I see the C++ zealots are still out there with a vengeance. Even advising to use std::async, which could actually not even launch a thread depending on the version of the compiler you use, unless you explicitely tell it to do so. – kuroi neko Nov 13 '15 at 10:24