Lifetime of promise and set_value_at_thread_exit - c++

Suppose we have the following code:
std::promise<int> promise;
auto future = promise.get_future();
const auto task = [](auto promise) {
try {
promise.set_value_at_thread_exit(int_generator_that_can_throw());
} catch (...) {
promise.set_exception_at_thread_exit(std::current_exception());
}
};
std::thread thread(task, std::move(promise));
// use future
thread.join();
I wonder if this code is correct and safe, and if no, why.
It appears to work fine when compiled with GCC, but crashes (no message is printed) when compiled with MSVC (2017). My guess is that a crash happens because promise local variable inside task goes out of scope and is destroyed too early. If I remove _at_thread_exit suffixes, this code works as expected (or appears to work). It also works correctly when the promise is captured:
const auto task = [p = std::move(promise)]() mutable {
/*...*/
};
Complete compilable example

Why does your code generate problems? Let's start with ansewer to 'when _at_thread_exit writes to shared state of std::future and std::promise?'. It happens after destruction of all thread local variables. Your lambda is called within the thread and after its scope is left, the promise is already destroyed. But what happens when thread calling your lambda has some thread-local variables? Well, the writing will occur after destruction of the std::promise object. Actually, the rest is really undefined in standard. It seems that passing data to shared state could be done after destruction of std::promise but information is not really there.
Simplest solution is of course this:
std::promise<int> promise;
auto future = promise.get_future();
const auto task = [](std::promise<int>& promise) {
try {
promise.set_value_at_thread_exit(int_generator_that_can_throw());
} catch (...) {
promise.set_exception_at_thread_exit(std::current_exception());
}
};
std::thread thread(task, std::ref(promise));
// use future
thread.join();

#include <future>
int main()
{
auto promise = std::make_shared<std::promise<int>>();
auto future = promise->get_future();
const auto task = [](const std::shared_ptr<std::promise<int>>& p)
{
try
{
p->set_value_at_thread_exit(42);
}
catch (...)
{
p->set_exception_at_thread_exit(std::current_exception());
}
};
std::thread thread(task, promise);
// use future
thread.join();
return 0;
}

Related

Using a C++ future as an intermediate value in a function stack results in a segfault

I'm having some trouble understanding C++11 promises, futures, and how they interact with different contexts.
Overall, my goal is to have a program that generates values in a compute thread and prints them in the main thread. Before the main thread gets the generated value, I want to intercept and change it. In the example code at the bottom, a future with value asdf is intercepted and redirect: is prepended, returning redirect:asdf to the future.
Compiling this code with LLVM 9, GCC 5/6/7, or Visual C++ 19 works fine. However, all blow up on f.get() in the lambda while throwing strange errors. For example, debugging using LLVM (LLDB) on MacOS gives EXC_BAD_ACCESS (code=1, address=0x18) from somewhere deep in the futures library, then croaks with exit code 11 (segfault). I do not think it is a problem with the library implementation because it behaves the same on all compilers.
There are a couple ways I've found to make the error go away, but then the code isn't in the structure I want. One is to simply return f; from push_redirect, discarding the async stuff and not changing the future's value. The other is to call push_new from main instead of push_redirect, also not changing the future's value. At the end of the day, I'd like to be able to stack as many of the future redirections as I want.
Is there anything I'm doing that's particularly wrong? I suspect it might have something to do with the capture-by-reference of the lambda, but I don't know how to arrange the code to avoid the capture-by-reference without using global variables. It could also be something to do with scope.
Below is a minimal example, stripped down from the larger program that is exhibiting this bug. It should compile on any online or offline C++ compiler that can handle C++11 or better.
#include <string>
#include <iostream>
#include <future>
#include <queue>
struct PromiseContainer {
std::promise<std::string> p;
};
std::queue<PromiseContainer *> q;
void other_thread()
{
std::string str("abcd");
while (true) {
while (q.empty());
auto pc = q.front();
q.pop();
if (pc == nullptr) break;
else {
pc->p.set_value(str);
delete pc;
}
}
}
std::future<std::string> push_new()
{
auto p = std::promise<std::string>();
auto f = p.get_future();
auto pc = new PromiseContainer();
pc->p = std::move(p);
q.push(pc);
return f;
}
std::future<std::string> push_redirect()
{
auto f = push_new();
return std::async(std::launch::deferred, [&]()->std::string {
return "redirect:" + f.get();
});
}
int main()
{
auto t = std::thread(other_thread);
auto f = push_redirect();
q.push((PromiseContainer *) nullptr);
f.wait();
std::cout << f.get() << std::endl;
t.join();
}
f in push_redirect is local variable so your lambda (with &)
[&]()->std::string {
return "redirect:" + f.get();
});
holds reference to this variable, when push_redirect ends f is deleted and you get undefined behaviour - thread created by async wants to read data which was destroyed.
If you are using C++14 you can move f future object in capture list of lambda:
std::future<std::string> push_redirect()
{
auto f = push_new();
return std::async(std::launch::deferred, [f = std::move(f)]() mutable ->std::string {
return "redirect:" + f.get();
});
}
You should also use mutex to synchronize access to your q queue.

How to start an empty thread using c++ [duplicate]

I'm getting into C++11 threads and have run into a problem.
I want to declare a thread variable as global and start it later.
However all the examples I've seen seem to start the thread immediately for example
thread t(doSomething);
What I want is
thread t;
and start the thread later.
What I've tried is
if(!isThreadRunning)
{
thread t(readTable);
}
but now t is block scope. So I want to declare t and then start the thread later so that t is accessible to other functions.
Thanks for any help.
std::thread's default constructor instantiates a std::thread without starting or representing any actual thread.
std::thread t;
The assignment operator moves the state of a thread object, and sets the assigned-from thread object to its default-initialized state:
t = std::thread(/* new thread code goes here */);
This first constructs a temporary thread object representing a new thread, transfers the new thread representation into the existing thread object that has a default state, and sets the temporary thread object's state to the default state that does not represent any running thread. Then the temporary thread object is destroyed, doing nothing.
Here's an example:
#include <iostream>
#include <thread>
void thread_func(const int i) {
std::cout << "hello from thread: " << i << std::endl;
}
int main() {
std::thread t;
std::cout << "t exists" << std::endl;
t = std::thread{ thread_func, 7 };
t.join();
std::cout << "done!" << std::endl;
}
As antred says in his answer, you can use a condition variable to make the thread to wait in the beginning of its routine.
Scott Meyers in his book “Effective Modern C++” (in the “Item 39: Consider void futures for one-shot event communication”) proposes to use void-future instead of lower level entities (boolean flag, conditional variable and mutex). So the problem can be solved like this:
auto thread_starter = std::promise<void>;
auto thread = std::thread([starter_future = thread_starter.get_future()]() mutable {
starter_future.wait(); //wait before starting actual work
…; //do actual work
});
…; //you can do something, thread is like “paused” here
thread_starter.set_value(); //“start” the thread (break its initial waiting)
Scott Meyers also warns about exceptions in the second … (marked by the you can do something, thread is like “paused” here comment). If thread_starter.set_value() is never called for some reasons (for example, due to exception throws in the second …), the thread will wait forever, and any attempt to join it would result in deadlock.
As both ways (condvar-based and future-based) contain hidden unsafety, and the first way (condvar-based) needs some boilerplate code, I propose to write a wrapper class around std::thread. Its interface should be similar to the one of std::thread (except that its instances should be assignable from other instances of the same class, not from std::thread), but contain additional void start() method.
Future-based thread-wrapper
class initially_suspended_thread {
std::promise<bool> starter;
std::thread impl;
public:
template<class F, class ...Args>
explicit initially_suspended_thread(F &&f, Args &&...args):
starter(),
impl([
starter_future = starter.get_future(),
routine = std::bind(std::forward<F>(f), std::forward<Args>(args)...)
]() mutable {if (starter_future.get()) routine();})
{}
void start() {starter.set_value(true);}
~initially_suspended_thread() {
try {starter.set_value(false);}
catch (const std::future_error &exc) {
if (exc.code() != std::future_errc::promise_already_satisfied) throw;
return; //already “started”, no need to do anything
}
impl.join(); //auto-join not-yet-“started” threads
}
…; //other methods, trivial
};
Condvar-based thread-wrapper
class initially_suspended_thread {
std::mutex state_mutex;
enum {INITIAL, STARTED, ABORTED} state;
std::condition_variable state_condvar;
std::thread impl;
public:
template<class F, class ...Args>
explicit initially_suspended_thread(F &&f, Args &&...args):
state_mutex(), state(INITIAL), state_condvar(),
impl([
&state_mutex = state_mutex, &state = state, &state_condvar = state_condvar,
routine = std::bind(std::forward<F>(f), std::forward<Args>(args)...)
]() {
{
std::unique_lock state_mutex_lock(state_mutex);
state_condvar.wait(
state_mutex_lock,
[&state]() {return state != INITIAL;}
);
}
if (state == STARTED) routine();
})
{}
void start() {
{
std::lock_guard state_mutex_lock(state_mutex);
state = STARTED;
}
state_condvar.notify_one();
}
~initially_suspended_thread() {
{
std::lock_guard state_mutex_lock(state_mutex);
if (state == STARTED) return; //already “started”, no need to do anything
state = ABORTED;
}
impl.join(); //auto-join not-yet-“started” threads
}
…; //other methods, trivial
};
There is no "standard" of creating a thread "suspended" which I assume is what you wanted to do with the C++ thread library. Because it is not supported on every platform that has threads, it is not there in the C++ API.
You might want to create a class with all the data it is required but not actually run your thread function. This is not the same as creating the thread but may be what you want. If so, create that, then later bind the object and its operator() or start() function or whatever to the thread.
You might want the thread id for your thread. That means you do actually need to start the thread function. However it can start by waiting on a condition variable. You then signal or broadcast to that condition variable later when you want it to continue running. Of course you can have the function check a condition after it resumes in case you might have decided to close it and not run it after all (in which case it will just return instantly).
You might want a std::thread object with no function. You can do that and attach it to a function later to run that function in a new thread.
I would give the thread a condition variable and a boolean called startRunning (initially set to false). Effectively you would start the thread immediately upon creation, but the first thing it would do is suspend itself (using the condition_variable) and then only begin processing its actual task when the condition_variable is signaled from outside (and the startRunning flag set to true).
EDIT: PSEUDO CODE:
// in your worker thread
{
lock_guard l( theMutex );
while ( ! startRunning )
{
cond_var.wait( l );
}
}
// now start processing task
// in your main thread (after creating the worker thread)
{
lock_guard l( theMutex );
startRunning = true;
cond_var.signal_one();
}
EDIT #2: In the above code, the variables theMutex, startRunning and cond_var must be accessible by both threads. Whether you achieve that by making them globals or by encapsulating them in a struct / class instance is up to you.
first declared in class m_grabber runs nothing. We assign member class object with new one with lambda function in launch_grabber method and thread with lambda runs within source class context.
class source {
...
std::thread m_grabber;
bool m_active;
...
}
bool source::launch_grabber() {
// start grabber
m_grabber = std::thread{
[&] () {
m_active = true;
while (true)
{
if(!m_active)
break;
// TODO: something in new thread
}
}
};
m_grabber.detach();
return true;
}
You could use singleton pattern. Or I would rather say antipattern.
Inside a singleton you would have std::thread object encapsulated. Upon first access to singleton your thread will be created and started.

Delayed start of a thread in C++ 11

I'm getting into C++11 threads and have run into a problem.
I want to declare a thread variable as global and start it later.
However all the examples I've seen seem to start the thread immediately for example
thread t(doSomething);
What I want is
thread t;
and start the thread later.
What I've tried is
if(!isThreadRunning)
{
thread t(readTable);
}
but now t is block scope. So I want to declare t and then start the thread later so that t is accessible to other functions.
Thanks for any help.
std::thread's default constructor instantiates a std::thread without starting or representing any actual thread.
std::thread t;
The assignment operator moves the state of a thread object, and sets the assigned-from thread object to its default-initialized state:
t = std::thread(/* new thread code goes here */);
This first constructs a temporary thread object representing a new thread, transfers the new thread representation into the existing thread object that has a default state, and sets the temporary thread object's state to the default state that does not represent any running thread. Then the temporary thread object is destroyed, doing nothing.
Here's an example:
#include <iostream>
#include <thread>
void thread_func(const int i) {
std::cout << "hello from thread: " << i << std::endl;
}
int main() {
std::thread t;
std::cout << "t exists" << std::endl;
t = std::thread{ thread_func, 7 };
t.join();
std::cout << "done!" << std::endl;
}
As antred says in his answer, you can use a condition variable to make the thread to wait in the beginning of its routine.
Scott Meyers in his book “Effective Modern C++” (in the “Item 39: Consider void futures for one-shot event communication”) proposes to use void-future instead of lower level entities (boolean flag, conditional variable and mutex). So the problem can be solved like this:
auto thread_starter = std::promise<void>;
auto thread = std::thread([starter_future = thread_starter.get_future()]() mutable {
starter_future.wait(); //wait before starting actual work
…; //do actual work
});
…; //you can do something, thread is like “paused” here
thread_starter.set_value(); //“start” the thread (break its initial waiting)
Scott Meyers also warns about exceptions in the second … (marked by the you can do something, thread is like “paused” here comment). If thread_starter.set_value() is never called for some reasons (for example, due to exception throws in the second …), the thread will wait forever, and any attempt to join it would result in deadlock.
As both ways (condvar-based and future-based) contain hidden unsafety, and the first way (condvar-based) needs some boilerplate code, I propose to write a wrapper class around std::thread. Its interface should be similar to the one of std::thread (except that its instances should be assignable from other instances of the same class, not from std::thread), but contain additional void start() method.
Future-based thread-wrapper
class initially_suspended_thread {
std::promise<bool> starter;
std::thread impl;
public:
template<class F, class ...Args>
explicit initially_suspended_thread(F &&f, Args &&...args):
starter(),
impl([
starter_future = starter.get_future(),
routine = std::bind(std::forward<F>(f), std::forward<Args>(args)...)
]() mutable {if (starter_future.get()) routine();})
{}
void start() {starter.set_value(true);}
~initially_suspended_thread() {
try {starter.set_value(false);}
catch (const std::future_error &exc) {
if (exc.code() != std::future_errc::promise_already_satisfied) throw;
return; //already “started”, no need to do anything
}
impl.join(); //auto-join not-yet-“started” threads
}
…; //other methods, trivial
};
Condvar-based thread-wrapper
class initially_suspended_thread {
std::mutex state_mutex;
enum {INITIAL, STARTED, ABORTED} state;
std::condition_variable state_condvar;
std::thread impl;
public:
template<class F, class ...Args>
explicit initially_suspended_thread(F &&f, Args &&...args):
state_mutex(), state(INITIAL), state_condvar(),
impl([
&state_mutex = state_mutex, &state = state, &state_condvar = state_condvar,
routine = std::bind(std::forward<F>(f), std::forward<Args>(args)...)
]() {
{
std::unique_lock state_mutex_lock(state_mutex);
state_condvar.wait(
state_mutex_lock,
[&state]() {return state != INITIAL;}
);
}
if (state == STARTED) routine();
})
{}
void start() {
{
std::lock_guard state_mutex_lock(state_mutex);
state = STARTED;
}
state_condvar.notify_one();
}
~initially_suspended_thread() {
{
std::lock_guard state_mutex_lock(state_mutex);
if (state == STARTED) return; //already “started”, no need to do anything
state = ABORTED;
}
impl.join(); //auto-join not-yet-“started” threads
}
…; //other methods, trivial
};
There is no "standard" of creating a thread "suspended" which I assume is what you wanted to do with the C++ thread library. Because it is not supported on every platform that has threads, it is not there in the C++ API.
You might want to create a class with all the data it is required but not actually run your thread function. This is not the same as creating the thread but may be what you want. If so, create that, then later bind the object and its operator() or start() function or whatever to the thread.
You might want the thread id for your thread. That means you do actually need to start the thread function. However it can start by waiting on a condition variable. You then signal or broadcast to that condition variable later when you want it to continue running. Of course you can have the function check a condition after it resumes in case you might have decided to close it and not run it after all (in which case it will just return instantly).
You might want a std::thread object with no function. You can do that and attach it to a function later to run that function in a new thread.
I would give the thread a condition variable and a boolean called startRunning (initially set to false). Effectively you would start the thread immediately upon creation, but the first thing it would do is suspend itself (using the condition_variable) and then only begin processing its actual task when the condition_variable is signaled from outside (and the startRunning flag set to true).
EDIT: PSEUDO CODE:
// in your worker thread
{
lock_guard l( theMutex );
while ( ! startRunning )
{
cond_var.wait( l );
}
}
// now start processing task
// in your main thread (after creating the worker thread)
{
lock_guard l( theMutex );
startRunning = true;
cond_var.signal_one();
}
EDIT #2: In the above code, the variables theMutex, startRunning and cond_var must be accessible by both threads. Whether you achieve that by making them globals or by encapsulating them in a struct / class instance is up to you.
first declared in class m_grabber runs nothing. We assign member class object with new one with lambda function in launch_grabber method and thread with lambda runs within source class context.
class source {
...
std::thread m_grabber;
bool m_active;
...
}
bool source::launch_grabber() {
// start grabber
m_grabber = std::thread{
[&] () {
m_active = true;
while (true)
{
if(!m_active)
break;
// TODO: something in new thread
}
}
};
m_grabber.detach();
return true;
}
You could use singleton pattern. Or I would rather say antipattern.
Inside a singleton you would have std::thread object encapsulated. Upon first access to singleton your thread will be created and started.

Futures vs. Promises

I'm confusing myself with difference between a future and a promise.
Obviously, they have different methods and stuff, but what is the actual use case?
Is it?:
when I'm managing some async task, I use future to get the value "in future"
when I'm the async task, I use promise as the return type to allow the user get a future from my promise
Future and Promise are the two separate sides of an asynchronous operation.
std::promise is used by the "producer/writer" of the asynchronous operation.
std::future is used by the "consumer/reader" of the asynchronous operation.
The reason it is separated into these two separate "interfaces" is to hide the "write/set" functionality from the "consumer/reader".
auto promise = std::promise<std::string>();
auto producer = std::thread([&]
{
promise.set_value("Hello World");
});
auto future = promise.get_future();
auto consumer = std::thread([&]
{
std::cout << future.get();
});
producer.join();
consumer.join();
One (incomplete) way to implement std::async using std::promise could be:
template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
typedef decltype(func()) result_type;
auto promise = std::promise<result_type>();
auto future = promise.get_future();
std::thread(std::bind([=](std::promise<result_type>& promise)
{
try
{
promise.set_value(func()); // Note: Will not work with std::promise<void>. Needs some meta-template programming which is out of scope for this question.
}
catch(...)
{
promise.set_exception(std::current_exception());
}
}, std::move(promise))).detach();
return std::move(future);
}
Using std::packaged_task which is a helper (i.e. it basically does what we were doing above) around std::promise you could do the following which is more complete and possibly faster:
template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
auto task = std::packaged_task<decltype(func())()>(std::forward<F>(func));
auto future = task.get_future();
std::thread(std::move(task)).detach();
return std::move(future);
}
Note that this is slightly different from std::async where the returned std::future will when destructed actually block until the thread is finished.

Replacing std::async with own version but where should std::promise live?

I'm using vc2011 and it turns out the std::async(std::launch::async, ... ) is a bit buggy (sometimes it does not spawn new threads and runs them in parallel, but instead reuses threads and runs task one after another). This is too slow when I'm doing expensive network calls. So I figured I'd write my own async function. I'm getting stuck though, where should std::promise live? In the 1) thread function, 2) async function, or 3) caller function.
Code:
#include <future>
#include <thread>
#include <iostream>
#include <string>
#include <vector>
std::string thFun() {
throw std::exception("bang!");
return "val";
}
std::future<std::string> myasync(std::promise<std::string>& prms) {
//std::future<std::string> myasync() {
//std::promise<std::string> prms; //needs to outlive thread. How?
std::future<std::string> fut = prms.get_future();
std::thread th([&](){
//std::promise<std::string> prms; //need to return a future before...
try {
std::string val = thFun();
prms.set_value(val);
} catch(...) {
prms.set_exception(std::current_exception());
}
});
th.detach();
return fut;
}
int main() {
std::promise<std::string> prms; //I really want the promise hidden iway in the myasync func and not live here in caller code but the promise needs to outlive myasync and live as long as the thread. How do I do this?
auto fut = myasync(prms);
//auto fut = myasync(); //Exception: future already retrieved
try {
auto res = fut.get();
std::cout << "Result: " << res << std::endl;
} catch(const std::exception& exc) {
std::cout << "Exception: " << exc.what() << std::endl;
}
}
I cant seem to get past the fact that the std::promise needs to outlive the async function (and live as long as the thread), so the promise cant live as a local variable in the async func. But the std::promise shouldn’t live in in the caller code either, as the caller only need to know about futures. And i dont know how to make the promise live in the thread function as async needs to return a future before it even calls the thread func. I’m scratching my head on this one.
Anyone got any ideas?
Edit: I'm highlighting this here as the top comment is a bit misinformed. While the default for std::asycn is allowed to be the dererred mode, when a launch policy of std::launch::async is explicitly set it must behave "as if" threads are spawned and run at once (see wording in en.cppreference.com/w/cpp/thread/async). See the example in pastebin.com/5dWCjjNY for one case where this is not the behavioured seen in vs20011. The solution works great and sped up my real world application by a factor of 10.
Edit 2: MS fixed the bug. More info here: https://connect.microsoft.com/VisualStudio/feedback/details/735731/std-async-std-launch-async-does-not-behave-as-std-thread
Here is one solution:
future<string> myasync()
{
auto prms = make_shared<promise<string>> ();
future<string> fut = prms->get_future();
thread th([=](){
try {
string val = thFun();
// ...
prms->set_value(val);
} catch(...) {
prms->set_exception(current_exception());
}
});
th.detach();
return fut;
}
Allocate promise on the heap, and then pass-by-value [=] a shared_ptr to it through to the lambda.
You need to move the promise into the new thread. Andrew Tomazos's answer does it by creating a std::promise with shared ownership, so that both threads can own the promise, and when the current one returns from the current scope only the new thread owns the promise, i.e. the ownership has been transferred. But std::promise is movable so it should be possible to move it directly into the new thread, except that the "obvious" solution of capturing it doesn't work because lambda's can't capture by move, only by copy (or by reference, which wouldn't work as you'd get a dangling reference.)
However, std::thread supports passing rvalue objects to the new thread's start function. so you can declare the lambda to take a std::promise argument by value, i.e. pass the promise to the lambda rather than capturing it, and then move the promise into one of the arguments of the std::thread e.g
std::future<std::string> myasync() {
std::promise<std::string> prms;
std::future<std::string> fut = prms.get_future();
std::thread th([&](std::promise<std::string> p){
try {
std::string val = thFun();
p.set_value(val);
} catch(...) {
p.set_exception(std::current_exception());
}
}, std::move(prms));
th.detach();
return fut;
}
This move the promise into the std::thread object, which then moves it (in the context of the new thread) into the lambda's parameter p.