10

Possible Duplicate:
C++: Simple return value from std::thread?

Is there anyway to get the return code from a std::thread? I have a function which returns a integer, and I want to be able to get the return code from the function when the thread is done executing.

Community
  • 1
  • 1
whoosy
  • 297
  • 2
  • 4
  • 10

4 Answers4

19

No, that's not what std::thread is for.

Instead, use async to get a future:

#include <future>

int myfun(double, char, bool);

auto f = std::async(myfun, arg1, arg2, arg3);  // f is a std::future<int>

// ...

int res = f.get();

You can use the wait_for member function of f (with zero timeout) to see if the result is ready.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I discovered that at least in VC11, std::async will not release all the resources of the thread until the end of the application, making possible to get memory leak false positive (if you are monitoring them using, for example Visual Leak Detector). So maybe providing a similar example using std::packaged_task and std::thread would be even better. Also async is not guaranteed to run in a separate thread. – Klaim Sep 07 '12 at 14:43
  • 4
    @Klaim: I don't understand `packaged_task` very well, nor do I know its idioms. Please do post it as an answer; it'll be for the good of everyone. – Kerrek SB Sep 07 '12 at 14:47
  • `valid` doesn't tell you when the result is ready, it tells you that the future has an associated state and will therefore *eventually* get a value. – Anthony Williams Sep 07 '12 at 15:04
  • @AnthonyWilliams: Oh, good point. Maybe `wait_for` with a zero timeout? – Kerrek SB Sep 07 '12 at 15:05
  • 1
    Yes, I'd use `wait_for` with a zero timeout to check for ready. – Anthony Williams Sep 07 '12 at 15:16
  • I added the example. I hope it is correct, please point me if I did wrong. I wrote the same code few days ago, following what I learnt in @AnthonyWilliams 's book on the subject XD – Klaim Sep 07 '12 at 15:23
  • 3
    @AnthonyWilliams: Oh, I didn't realize, you're the guy whose book I just bought! This is exciting. – Kerrek SB Sep 07 '12 at 15:26
  • @Klaim: Great, thanks, I'll read it in a bit! – Kerrek SB Sep 07 '12 at 15:28
  • @KerrekSB but the std::async::get() blocks! What a reason for a separate thread if we got blocked on this `get()` call… – Hi-Angel Aug 07 '14 at 13:04
  • 1
    @YagamyLight: It *may* block. Of course you wouldn't create an `async` future and immediately call `get`. The idea is that you have other stuff to do, and you only block when you absolutely need the result. – Kerrek SB Aug 07 '14 at 14:08
  • @KerrekSB thank you, I already got the idea: if I don't wanna to be blocked, I need to ensure first that the thread has gone. Tbh, that was initial reason why I was seeked for a way to get return of a thread. But I just figure out that I choose a wrong way. – Hi-Angel Aug 07 '14 at 14:22
  • is there a performance penalty for using future vs thread? – kirill_igum Feb 05 '15 at 11:48
16

As others have suggested, the facilities in <future> can be used for this. However I object to the answer

No, you can't do this with std::thread

Here is one way to do what you want with std::thread. It is by no means the only way:

#include <thread>
#include <iostream>

int func(int x)
{
    return x+1;
}

int main()
{
    int i;
    std::thread t([&] {i = func(2);});
    t.join();
    std::cout << i << '\n';
}

This will portably output:

3
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • 1
    Yes, but you're not really getting it from the `thread` object; you're getting it because you created a functor that uses a reference to retrieve the variable. Anyone can do that; the question is about capturing the return value from the `thread` object. – Nicol Bolas Sep 07 '12 at 15:34
  • 1
    The question has two sentences. I answered the second one. – Howard Hinnant Sep 07 '12 at 15:55
  • @HowardHinnant: You can of course make the thread manipulate any old shared state (which is probably how you *should* be doing it anyway). But you're still not "getting the return value of `std::thread`... rather, you've got a sort of poor-man's version of the `packaged_task` I suppose. But this is certainly a very useful observation. (By the way, the second sentence isn't a question ;-).) – Kerrek SB Sep 08 '12 at 10:10
14

Kerrek SB is correct with his answer, but I suggested to add another example (which he suggested should be an answer, so here it is).

I discovered recently that at least in VC11, std::async will not release all the resources of the thread until the end of the application, making possible to get memory leak false positive (if you are monitoring them using, for example Visual Leak Detector).

Here I mean that in most basic applications it is not worth looking at the rest of this answer, but if like me you need to check memory leaks and can't afford to let false positive, like static data not released at the end of the main function. If it's your case, then this might help.

std::async is not guaranteed to run in a separate thread by default, it is only if you use std::launch::async as first parameter. Otherwise the implementation decide what to do, and that's why VC11 implementation will use the new Microsoft Concurrency Runtime task manager to manage the provided function as a task pushed in a task pool, which mean threads are maintained and managed in a transparent way. There are ways to explicitely terminate the task manager but that's too platform specific, making async a poor choice when you want exactly 1) be sure to launch a thread and 2) get a result later and 3) be sure the thread is fully released when you get the result.


The alternative that does exactly that is to use std::packaged_task and std::thread in combination with std::future. The way it is done is almost similar to using std::async, just a bit more verbose (which mean you can generalize it in a custom template function if you want).

#include <packaged_task>
#include <thread>

int myfun(double, char, bool);

std::packaged_task<int(double, char, bool)> task(myfun, arg1, arg2, arg3); 

auto f = task.get_future();  // f is a std::future<int> 

First we create a task, basically an object containing both the function and the std::promise that will be associated with the future. std::packaged_task works mostly like an augmented version of std::function:

Now we need to execute the thread explicitly:

std::thread thread(std::move(task));

thread.detach();

The move is necessary because std::packaged_task is not copyable. Detaching the thread is only necessary if you only want to synchronize using the future – otherwise you will need to join the thread explicitly. If you don't, when thread's destructor is called, it will just call std::terminate().

// ...

int res = f.get(); // Synchronization and retrieval.
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
Klaim
  • 67,274
  • 36
  • 133
  • 188
  • [As I just read](http://en.cppreference.com/w/cpp/thread/async) the std::async may not run asynchronously if the function queries for the result, i.e. if it is in fact just waits for the thread to return, and in this case for a separate thread no reason indeed. – Hi-Angel Aug 07 '14 at 12:50
3

Here's an example using packaged_task:

#include <future>
#include <iostream>

void task_waiter(std::future<int>&& f) {
    std::future<int> ft = std::move(f);
    int result = ft.get();
    std::cout << result << '\n';
}

int the_task() {
    return 17;
}

int main() {
    std::packaged_task<int()> task(the_task);
    std::thread thr(task_waiter, task.get_future());
    task();
    thr.join();
    return 0;
}
Pete Becker
  • 74,985
  • 8
  • 76
  • 165