how to safely register std::stop_callback with std::jthread - c++

I'm a bit confused about how to safely register callbacks for jthread. You need the token so that means that you would need to do the registration after creating the jthread which means that the callback would be destroyed before the jthread. In the example below cb5 and cb6 obviously get destroyed before the dtor of the jthread starts so they automatically deregister themselves and never execute. Conversely, cb1 and cb2 are explicitly destroyed after the destruction of jthread so they are guaranteed to execute as a side effect to the dtor requesting a stop. Now the confusing part is that I can not find any guarantees that cb3 and cb4 are guaranteed to execute. There is nothing I could find that says that requesting stop would atomically change set the stop flag and execute all the callbacks for example. On the other hand, I looked at the Implementation:223 of request_stop and it seems that it does the following
takes a lock
set the stop flag and fetch the last registered stop callback
release the lock
run the callback
release the binary semaphore (which the destructor of that callback waits on)
tries to reacquire the lock to execute the next callback
Now finally to the question, according to the above, the execution of cb3 and cb4 is racing with their destructors (at least cb3, because cb4 will be chosen for execution under the same lock that will be used to set the stop flag, but again I could not find that guarantee for cb4 mentioned somewhere). So how can one use a stop_callback properly with a jthread without calling request_stop explicitly? you can't register the callbacks after because they will be destroyed before like cb5 and cb6 and you can't register them withing the thread because they are not guaranteed to execute like cb3 and cb4 and I do not think that it was intended to give them a longer lifetime in the convoluted way of cb1 and cb2
#include <chrono>
#include <iostream>
#include <stop_token>
#include <thread>
int main(int argc, const char * const * const argv)
{
using namespace std::chrono_literals;
const auto _cb1 = []() -> void {
std::cout << "cb1\n";
std::this_thread::yield();
std::this_thread::sleep_for(10s);
};
const auto _cb2 = []() -> void {
std::cout << "cb2\n";
std::this_thread::yield();
std::this_thread::sleep_for(10s);
};
using CB1 =
decltype(std::stop_callback(std::declval<std::stop_token>(), _cb1));
using CB2 =
decltype(std::stop_callback(std::declval<std::stop_token>(), _cb2));
std::byte storage1[sizeof(CB1)];
std::byte storage2[sizeof(CB2)];
const CB1 * cb1 = nullptr;
const CB2 * cb2 = nullptr;
{
std::jthread worker([](const std::stop_token & stop_token) {
std::stop_callback cb3(stop_token, [] {
std::cout << "cb3\n";
std::this_thread::yield();
std::this_thread::sleep_for(10s);
});
std::stop_callback cb4(stop_token, [] {
std::cout << "cb4\n";
std::this_thread::yield();
std::this_thread::sleep_for(10s);
});
while (!stop_token.stop_requested())
{
}
});
cb1 = new (&storage1) std::stop_callback(worker.get_stop_token(), _cb1);
cb2 = new (&storage2) std::stop_callback(worker.get_stop_token(), _cb2);
std::stop_callback cb5(worker.get_stop_token(), [] {
std::cout << "cb5\n";
std::this_thread::yield();
std::this_thread::sleep_for(10s);
});
std::stop_callback cb6(worker.get_stop_token(), [] {
std::cout << "cb6\n";
std::this_thread::yield();
std::this_thread::sleep_for(10s);
});
std::this_thread::sleep_for(2s);
}
cb1->~CB1();
cb2->~CB2();
return 0;
}

The standard directly states that:
A call to request_­stop that returns true synchronizes with a call to stop_requested on an associated stop_­token or stop_­source object that returns true.
This means that a call to stop_requested that returns true "happens after" any request_stop that returns true. So your while loop cannot exit until a call to request_stop actually returns true to some thread. More importantly, it cannot exit until such a call returns.
request_stop is explicitly stated to:
If the request was made, the callbacks registered by associated stop_callback objects are synchronously called.
Being called "synchronously" means exactly that: this function will either call them on the thread requesting the stop or it will synchronize with whatever thread(s) they do get called on. The main point being that until those callbacks are finished, this function does not return.
And until this function returns, stop_requested will not return true, as previously stated.
So there is no data race. The callbacks will not be destroyed before the thread exits.

Related

Waiting for a thread to finish and future

Having such simple code:
void func(std::promise<int>* p) {
int a = 10, b = 5;
int result = a + b;
std::cout << "From inside the Thread...." << std::endl;
p->set_value(result);
}
int FP_main() {
std::promise<int> p;
std::future<int> f = p.get_future();
std::thread th(func, &p);
int ret = f.get();
std::cout << "returned val: " << ret << std::endl;
th.join();
return 0;
}
Why do we need the join function call if there is get call just 2 lines above? Isn't the get function waiting for a thread to finish?
Because the thread is not the promise.
Promise is finished, but thread is not.
p->set_value(result);
// ...
// HERE
// ...
}
That are the last lines of func. The thread will now do its cleanups, will call destructors, etc. All while the promise is finished. Of couse, in 'HERE' the thread may a ton of other work - you can write a 1-hour long task in HERE to keep the thread alive and it will have nothing to do with the promise.
That's probably all clear already.
The last interesting bit is here:
int FP_main() {
//...
std::thread th(func, &p);
//...
th.join();
return 0;
}
The 'th' is a local variable. When the main() returns, the destructor of th will be invoked. And that destructor throws an exception when the thread in question is not finished and not join'ed.
If the thread were busy after setting the value of the promise (i.e. doing destructors, or doing some 1-hour-long job), the std::thread's destructor invoked by } after return 0; would throw and crash the program. Hence, you need to join.
Why do we need the join function call if there is get call just 2 lines above?
Destroying a joinable std::thread object results in std::terminate() being called. This is regardless of whether or not its associated thread is done. So, the call to get() on the future is irrelevant when it comes to having to call join() on a joinable std::thread object before it is destroyed.
If you don't want to have to call join(), then you could just call detach() on the std::thread somewhere before its destruction. This way, the thread won't be joinable at the moment of destruction.

Is std::call_once a blocking call?

I'm using std::call_once in my code to initialize some shared variables only once. The calling code is inside a callback that is triggered by multiple threads.
What I'm interested to know, since I couldn't find it in the documentation is whether std::call_once is blocking essentially as if there was a std::lock_guard instead?
In practice it looks like this is the case.
For example, the following will print "Done" before any print() will be called:
#include <future>
#include <iostream>
#include <thread>
#include <mutex>
std::once_flag flag;
void print()
{
for(int i=0;i<10;i++)
{
std::cout << "Hi, my name is " << std::this_thread::get_id()
<< ", what?" << std::endl;
}
}
void do_once()
{
std::cout << "sleeping for a while..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "Done" << std::endl;
}
void work()
{
std::call_once(flag, [](){ do_once(); });
print();
}
int main()
{
auto handle1 = std::async(std::launch::async, work);
auto handle2 = std::async(std::launch::async, work);
auto handle3 = std::async(std::launch::async, work);
auto handle4 = std::async(std::launch::async, work);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
I'm assuming this is indeed the case (since I don't see how it could be implemented otherwise), but is this behavior guaranteed or could there be a compiler that decides that std::call_once will indeed be called once but allow other threads to continue and just ignore this call?
Yes std::call_once is a blocking call. From [thread.once.callonce] we have
Effects: An execution of call_once that does not call its func is a passive execution. An execution of call_once that calls its func is an active execution. An active execution shall call INVOKE (DECAY_COPY ( std::forward<Callable>(func)), DECAY_COPY (std::forward<Args>(args))...). If such a call to func throws an exception the execution is exceptional, otherwise it is returning. An exceptional execution shall propagate the exception to the caller of call_once. Among all executions of call_once for any given once_flag: at most one shall be a returning execution; if there is a returning
execution, it shall be the last active execution; and there are passive executions only if there is a returning execution. [ Note: passive executions allow other threads to reliably observe the results produced by the earlier returning execution. —end note ]
Synchronization: For any given once_flag: all active executions occur in a total order; completion of an active execution synchronizes with (1.10) the start of the next one in this total order; and the returning execution synchronizes with the return from all passive executions.
emphasis mine
This means that all calls to call_once will wait until the function passed to call_once completes. In your case that means do_once() must be called before any thread calls print()

std::thread thread spun off in object, when does it terminate?

If I spin off an std::thread in the constructor of Bar when does it stop running? Is it guaranteed to stop when the Bar instance gets destructed?
class Bar {
public:
Bar() : thread(&Bar:foo, this) {
}
...
void foo() {
while (true) {//do stuff//}
}
private:
std::thread thread;
};
EDIT: How do I correctly terminate the std::thread in the destructor?
If I spin off an std::thread in the constructor of Bar when does it
stop running?
the thread will run as long as it executing the callable you provided it, or the program terminates.
Is it guaranteed to stop when the Bar instance gets destructed?
No. In order to guarantee that, call std::thread::join in Bar destructor.
Actually, if you hadn't call thread::join or thread::detach prior to Bar::~Bar, than your application will be terminated by calling automatically to std::terminate. so you must call either join (preferable) or detach (less recommended).
you also want to call therad::join on the object destructor because the spawned thread relies on the object to be alive, if the object is destructed while your thread is working on that object - you are using destructed object and you will have undefined behavior in your code.
Short answer: Yes and no. Yes, the thread ends, but not by the usual way (killing the thread), but by the main thread exiting due to a std::terminate call.
Long answer: The thread can only be safely destructed when the underlying function (thread) has finished executing. This can be done in 2 ways
calling join(), which waits for the thread to finish (in your case, never)
calling detach(), which detaches the thread from the main thread (in this case, the thread will end when the main thread closes - when the program terminates).
If the destructor is called if all of those conditions don't apply, then std::terminate is called:
it was default-constructed
it was moved from
join() has been called
detach() has been called
The C++ threading facilities do not include a built-in mechanism for terminating a thread. Instead, you must decide for yourself: a) a mechanism to signal the thread that it should terminate, b) that you do not care about the thread being aborted mid-operation when the process terminates and the OS simply ceases to run it's threads any more.
The std::thread object is not the thread itself but an opaque object containing a descriptor/handle for the thread, so in theory it could be destroyed without affecting the thread, and there were arguments for and against automatic termination of the thread itself. Instead, as a compromise, it was made so that destroying a std::thread object while the thread remained running and attached would cause the application to terminate.
As a result, In it's destructor there is some code like this:
~thread() {
if (this->joinable())
std::terminate(...);
}
Here's an example of using a simple atomic variable and checking for it in the thread. For more complex cases you may need to consider a condition_variable or other more sophisticated signaling mechanism.
#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>
class S {
std::atomic<bool> running_;
std::thread thread_;
public:
S() : running_(true), thread_([this] () { work(); }) {}
void cancel() { running_ = false; }
~S() {
if ( running_ )
cancel();
if ( thread_.joinable() )
thread_.join();
}
private:
void work() {
while ( running_ ) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "tick ...\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "... tock\n";
}
std::cout << "!running\n";
}
};
int main()
{
std::cout << "main()\n";
{
S s;
std::this_thread::sleep_for(std::chrono::milliseconds(2750));
std::cout << "end of main, should see a tock and then end\n";
}
std::cout << "finished\n";
}
Live demo: http://coliru.stacked-crooked.com/a/3b179f0f9f8bc2e1

Why C++ async run sequentially without future?

#include <future>
#include <iostream>
void main()
{
std::async(std::launch::async,[] {std::cout << "async..." << std::endl; while (1);});
std::cout << "runing main..." << std::endl;
}
In this code, only "async..." will be outputted, which means the code is blocked at async. However, if I add future and let the statement become:
std::future<bool> fut = std::async([]
{std::cout << "async..." << std::endl; while (1); return false; });
Then everything runs smoothly (it will not be blocked). I am not sure why it happen in this way. I think async is supposed to run in a separate thread.
From encppreference.com:
If the std::future obtained from std::async is not moved from or bound to a reference, the destructor of the std::future will block at the end of the full expression until the asynchronous operation completes, essentially making code such as the following synchronous:
std::async(std::launch::async, []{ f(); }); // temporary's dtor waits for f()
std::async(std::launch::async, []{ g(); }); // does not start until f() completes
If I did get that right, it comes from these parts of the standard (N4527):
§30.6.6 [futures.unique_future]:
~future();
Effects:
— releases any shared state (30.6.4);
§30.6.4#5 [futures.state] (emphasis is mine):
When an asynchronous return object or an asynchronous provider is said to release its shared state, it means:
[...].
— these actions will not block for the shared state to become ready, except that it may block if all of the following are true: the shared state was created by a call to std::async, the shared state is not yet ready, and this was the last reference to the shared state.
Since you did not store the result of your first std::async call, the destructor of std::future is called and since all 3 conditions are met:
the std::future was created via std::async;
the shared state is not yet ready (due to your infinite loop);
there is no remaining reference to this future
...then the call is blocking.

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.