C++: Simple Return Value from Std::Thread

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

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).

Can one retrieve the return value of a thread function in C++11?

You can follow this sample code to get the return value from a thread :-

int main()
{
auto future = std::async(func_1, 2);

//More code later

int number = future.get(); //Whole program waits for this

// Do something with number

return 0;
}

In short, .get() gets the return value, you can typecast and use it then.

How to get a return value from a thread?

For obtaining return values form functions that are meant to be run in background, you may want to consider std::future instead of directly creating an std::thread object. You can use the std::async() function template to start an asynchronous task. It returns an std::future object that will eventually contain the return value of the function passed:

auto res = std::async(fun);

// ... optionally do something else

std::cout << res.get() << '\n';

That is, you create an std::future<int> by calling std::async(func). Then, when you need fun()'s return value, you simply call the get() member function on the future. If the future isn't ready yet (i.e., if it doesn't have the result yet), then the thread will block until it is.


Why not directly use std::thread

The problem with std::thread is that it doesn't provide a direct mechanism for transferring the return value of the callable passed at its construction. For example, suppose you want to start a new thread with std::thread to calculate the sum of two integers with the following function:

int sum(int a, int b) { return a + b; }

What you would probably try is:

std::thread th_sum(sum, 1, 2);

// ... optionally do something else

th_sum.join();
// calculation is finished, but where is the result?

The thread represented by th_sum does calculate the sum of 1 and 2. However, you don't get sum()'s return value, i.e., the result, from the associated std::thread object.

Instead, what you could do to handle this deficiency is, for example, to create a wrapper function for sum() that has an out parameter for the result instead of returning it:

void sum_outparam(int a, int b, int& res) { res = sum(a, b); }

Then, you can start a new thread for running this wrapper function and with help of std::ref() you will obtain the result in res:

int res;
std::thread th_sum(sum_outparam, 1, 2, std::ref(res));

// ... optionally do something else


th_sum.join();
// now, res contains the result

Return a value from a thread in C++11

Lauching a thread and terminating it require many hundreds of machine cycles. But that's only a beginning. Context switches between threads, that are bound to happen if the threads are doing anything useful, will repeatedly consume even more many hundreds of machine cycles. The execution context of all these threads will consume many a byte of memory, which in turn will mess up many a line of cache, thus hindering the CPU efforts for yet another great deal of many hundreds of machine cycles.

As a matter of fact, doing anything with multitasking is a great consumer of many hundreds of machine cycles. Multitasking only becomes profitable in terms of CPU power usage when you manage to get enough processors working on lumps of data that are conceptually independent (so parallel processing won't threaten their integrity) and big enough to show a net gain compared with a monoprocessor version.

In all other cases, multitasking is inherently inefficient in all domains but one: reactivity. A task can react very quickly and precisely to an external event, that ultimately comes from some external H/W component (be it the internal clock for timers or your WiFi/Ethernet controller for network traffic).

This ability to wait for external events without wasting CPU is what increases the overall CPU efficiency. And that's it.

In terms of other performance parameters (memory consumption, time wasted inside kernel calls, etc), launching a new thread is always a net loss.

In a nutshell, the art of multitasking programming boils down to:

  • identifying the external I/O flows you will have to handle
  • taking reactivity requirements into account (remembering that more reactive = less CPU/memory efficient 99% of the time)
  • setting up handlers for the required events with a reasonable efficiency/ease of maintenance compromise.

Multiprocessor architectures are adding a new level of complexity, since any program can now be seen as a process having a number of external CPUs at hand, that could be used as additional power sources. But your problem does not seem to have anything to do with that.

A measure of multitasking efficiency will ultimately depend on the number of external events a given program is expected to cope with simultaneously and within a given set of reactivity limits.

At last I come to your particular question.

To react to external events, launching a task each time a new twig or bit of dead insect has to be moved around the anthill is a very coarse and inefficient approach.

You have many powerful synchronization tools at your disposal, that will allow you to react to a bunch of asynchronous events from within a single task context with (near) optimal efficiency at (virtually) no cost.

Typically, blocking waits on multiple inputs, like for instance the unix-flavoured select() or Microsoft's WaitForMultipleEvents() counterpart.

Using these will give you a performance boost incomparably greater than the few dozen CPU cycles you could squeeze out of this task-result-gathering-optimization project of yours.

So my answer is: don't bother with optimizing thread setup at all. It's a non-issue.

Your time would be better spent rethinking your architecture so that a handful of well thought out threads could replace the hordes of useless CPU and memory hogs your current design would spawn.

How would I return a value while running a function from a thread

You can't return a value from a function using std::thread but you can change the structure of the std::thread to get your value or use std::sync which returns an std::future<T> holding your value, as follows

#include <iostream>
#include <thread>

int func(int a)
{
int b = a * a;
return b;
}

int main()
{
int result;
std::thread t([&] { result = func(3); });
t.join();
std::cout << result;
return 0;
}

or

#include <iostream>
#include <future>
int main()
{
auto f = std::async(std::launch::async, func, 3);
std::cout << f.get();
return 0;
}

C++ Get the return value from a threaded function later

You're requesting the result immediately rather than doing something else and then getting the result when you need it. If you do this:

int main()
{
auto future = std::async(func_1, 2);

//More code later

int number = future.get(); //Whole program waits for this

// Do something with number

return 0;
}

Then you can do something else in the More code later bit and then block when you need the result by calling get().

Alternatively you can poll to see if the value is available using either wait_for or wait_until and do something if the result is not ready.

Can I return std::thread

Yes, it's safe, as long as the function's return value is used to initialize or assign to another std::thread object.

The only precondition for std::thread's destructor is that joinable() is false:

[thread.thread.destr]

~thread();

    Effects: If joinable(), calls terminate(). Otherwise, has no effects.

To be joinable(), the thread must have an ID not equal to a value-initialized ID:

[thread.thread.member]

bool joinable() const noexcept;

    Returns: get_­id() != id().

And std::thread's move constructor and move-assignment operator specify that a moved-from thread will have an ID equal to a value-initalized ID, and therefore will not be joinable():

[thread.thread.constr]

thread(thread&& x) noexcept;

    Postconditions: x.get_­id() == id() and get_­id() returns the value of x.get_­id() prior to the start of construction.

[thread.thread.assign]

thread& operator=(thread&& x) noexcept;

    ...

    Postconditions: x.get_­id() == id() and get_­id() returns the value of x.get_­id() prior to the assignment.

    ...

Since getWindowThread returns a function-local variable, its return value will be move-constructed from the returned object, and since winT will be move-constructed from the value returned by getWindowThread, your example is safe. The returned thread object is no longer joinable and can be destroyed.

However, if the returned value is not used to initialize or assign to another std::thread object, its destructor will call std::terminate() and crash your program. For this reason, I would recommend adding the [[nodiscard]] attribute to your function to ensure your compiler at least issues a warning in this dangerous situation (if you have access to C++17 features, otherwise there are compiler-specific extensions to enable the same behavior):

[[nodiscard]] std::thread getWindowThread(std::function<void()> f) {
std::thread t(f);
return t;
}


Related Topics



Leave a reply



Submit