Memory visibility in C++ concurrency (no data race) - c++

It is a follow up question of Shared_ptr and Memory Visibility in c++ and Create object in thread A, use in thread B. Mutex required?.
This question is more about memory visibility rather than data race.
In Java, I have:
ExecutorService executor = Executors.newSingleThreadExecutor();
Integer i = new Integer(5); // no write to i afterwards
executor.submit(() -> {
System.out.println(i);
});
I don't think this is thread-safe. Because there is no need to put value 5 in the main memory, it could stay in the main thread's CPU cache. Since there is no memory barrier, the executor thread is not guaranteed to see the value 5. To make sure the value is in the main memory, you either use synchronization, or use AtomicInteger, or volatile int.
If you do something similar with shared_ptr in C++, is it safe?
auto sp = std::make_shared<int>(5); // no write to the int afterwards
myExecutor.submit([sp](){
std::cout << sp;
});
Is the executor thread guaranteed to see the value 5? Note that the shared_ptr is copied to the lambda, not the int.
Here is a more complete example:
Suppose I have a main thread and worker thread. In main thread I've constructed a shared_ptr<Object> and copy the shared_ptr to the worker thread, is this safe to use the copy of the shared_ptr if there is no synchronization in Object class at all (NO write to the object after construction)?
My main puzzle is, the Object is constructed in main thread on the heap, the shared_ptr is copied but not the Object. Will the worker thread definitely have the memory visibility of the Object? Would it be possible that the value of Object is actually in main thread's CPU cache and not in the main memory?
struct WorkingQueue{
WorkingQueue()=default;
void push(std::function<void()> task){
std::lock_guard<std::mutex> lock{mutex};
queue.push(std::move(task));
}
std::optional<std::function<void()>> popIfNotEmpty(){
std::lock_guard<std::mutex> lock{mutex};
if(queue.empty()){
return std::nullopt;
}
auto task = queue.front();
queue.pop();
return task;
}
bool empty(){
std::lock_guard<std::mutex> lock{mutex};
return queue.empty();
}
mutable std::mutex mutex;
std::queue<std::function<void()>> queue;
};
int main(){
WorkingQueue queue;
std::atomic<bool> stopFlag{false};
auto f = std::async(std::launch::async, [&queue, &stopFlag](){
while(!stopFlag || !queue.empty()){
auto task = queue.popIfNotEmpty();
if(task){
(*task)();
}
}
});
auto sp = std::make_shared<int>(5);
queue.push([sp](){
std::cout << *sp;
});
stopFlag = true;
f.get();
}
Is this programmer guaranteed to output 5?

is this safe to use the copy of the shared_ptr if there is no synchronization in Object class at all
Yes, std::shared_ptr is synchronized so that it's reference count is thread safe. Read/write synchronization of the object it points to, however, is up to you.
Edit after question edited:
Is the executor thread guaranteed to see the value 5?
No, this is exactly the same as passing a raw pointer to your myExecutor thread.

Related

Destructor, when object's dynamic variable is locked by mutex will not free it?

I'm trying to solve some complicated (for me at least) asynchronous scenario at once, but I think it will be better to understand more simple case.
Consider an object, that has allocated memory, carrying by variable:
#include <thread>
#include <mutex>
using namespace std;
mutex mu;
class Object
{
public:
char *var;
Object()
{
var = new char[1]; var[0] = 1;
}
~Object()
{
mu.lock();
delete[]var; // destructor should free all dynamic memory on it's own, as I remember
mu.unlock();
}
}*object = nullptr;
int main()
{
object = new Object();
return 0;
}
What if while, it's var variable in detached, i.e. asynchronous thread, will be used, in another thread this object will be deleted?
void do_something()
{
for(;;)
{
mu.lock();
if(object)
if(object->var[0] < 255)
object->var[0]++;
else
object->var[0] = 0;
mu.unlock();
}
}
int main()
{
object = new Object();
thread th(do_something);
th.detach();
Sleep(1000);
delete object;
object = nullptr;
return 0;
}
Is is it possible that var will not be deleted in destructor?
Do I use mutex with detached threads correctly in code above?
2.1 Do I need cover by mutex::lock and mutex::unlock also delete object line?
I also once again separately point that I need new thread to be asynchronous. I do not need the main thread to be hanged, while new is running. I need two threads at once.
P.S. From a list of commentaries and answers one of most important thing I finally understood - mutex. The biggest mistake I thought is that already locked mutex skips the code between lock and unlock.
Forget about shared variables, mutex itself has noting to do with it. Mutex is just a mechanism for safely pause threads:
mutex mu;
void a()
{
mu.lock();
Sleep(1000);
mu.unlock();
}
int main()
{
thread th(a);
th.detach();
mu.lock(); // hangs here, until mu.unlock from a() will be called
mu.unlock();
return;
}
The concept is extremely simple - mutex object (imagine) has flag isLocked, when (any) thread calls lock method and isLocked is false, it just sets isLocked to true. But if isLocked is true already, mutex somehow on low-level hangs thread that called lock until isLocked will not become false. You can find part of source code of lock method scrolling down this page. Instead of mutex, probably just a bool variable could be used, but it will cause undefined behaviour.
Why is it referred to shared stuff? Because using same variable (memory) simultaneously from multiple threads makes undefined behaviour, so one thread, reaching some variable that currently can be used by another - should wait, until another will finish working with it, that's why mutex is used here.
Why accessing mutex itself from different threads does not make undefined behaviour? I don't know, going to google it.
Do I use mutex with detached threads correctly in code above?
Those are orthogonal concepts. I don't think mutex is used correctly since you only have one thread mutating and accessing the global variable, and you use the mutex to synchronize waits and exits. You should join the thread instead.
Also, detached threads are usually a code smell. There should be a way to wait all threads to finish before exiting the main function.
Do I need cover by mutex::lock and mutex::unlock also delete object line?
No since the destructor will call mu.lock() so you're fine here.
Is is it possible that var will not be deleted in destructor?
No, it will make you main thread to wait though. There are solutions to do this without using a mutex though.
There's usually two way to attack this problem. You can block the main thread until all other thread are done, or use shared ownership so both the main and the thread own the object variable, and only free when all owner are gone.
To block all thread until everyone is done then do cleanup, you can use std::barrier from C++20:
void do_something(std::barrier<std::function<void()>>& sync_point)
{
for(;;)
{
if(object)
if(object->var[0] < 255)
object->var[0]++;
else
object->var[0] = 0;
} // break at a point so the thread exits
sync_point.arrive_and_wait();
}
int main()
{
object = new Object();
auto const on_completion = []{ delete object; };
// 2 is the number of threads. I'm counting the main thread since
// you're using detached threads
std::barrier<std::function<void()>> sync_point(2, on_completion);
thread th(do_something, std::ref(sync_point));
th.detach();
Sleep(1000);
sync_point.arrive_and_wait();
return 0;
}
Live example
This will make all the threads (2 of them) wait until all thread gets to the sync point. Once that sync point is reached by all thread, it will run the on_completion function, which will delete the object once when no one needs it anymore.
The other solution would be to use a std::shared_ptr so anyone can own the pointer and free it only when no one is using it anymore. Note that you will need to remove the object global variable and replace it with a local variable to track the shared ownership:
void do_something(std::shared_ptr<Object> object)
{
for(;;)
{
if(object)
if(object->var[0] < 255)
object->var[0]++;
else
object->var[0] = 0;
}
}
int main()
{
std::shared_ptr<Object> object = std::make_shared<Object>();
// You need to pass it as parameter otherwise it won't be safe
thread th(do_something, object);
th.detach();
Sleep(1000);
// If the thread is done, this line will call delete
// If the thread is not done, the thread will call delete
// when its local `object` variable goes out of scope.
object = nullptr;
return 0;
}
Is is it possible that var will not be deleted in destructor?
With
~Object()
{
mu.lock();
delete[]var; // destructor should free all dynamic memory on it's own, as I remember
mu.unlock();
}
You might have to wait that lock finish, but var would be deleted.
Except that your program exhibits undefined behaviour with non protected concurrent access to object. (delete object isn't protected, and you read it in your another thread), so everything can happen.
Do I use mutex with detached threads correctly in code above?
Detached or not is irrelevant.
And your usage of mutex is wrong/incomplete.
which variable should your mutex be protecting?
It seems to be a mix between object and var.
If it is var, you might reduce scope in do_something (lock only in if-block)
And it misses currently some protection to object.
2.1 Do I need cover by mutex::lock and mutex::unlock also delete object line?
Yes object need protection.
But you cannot use that same mutex for that. std::mutex doesn't allow to lock twice in same thread (a protected delete[]var; inside a protected delete object) (std::recursive_mutex allows that).
So we come back to the question which variable does the mutex protect?
if only object (which is enough in your sample), it would be something like:
#include <thread>
#include <mutex>
using namespace std;
mutex mu;
class Object
{
public:
char *var;
Object()
{
var = new char[1]; var[0] = 1;
}
~Object()
{
delete[]var; // destructor should free all dynamic memory on it's own, as I remember
}
}*object = nullptr;
void do_something()
{
for(;;)
{
mu.lock();
if(object)
if(object->var[0] < 255)
object->var[0]++;
else
object->var[0] = 0;
mu.unlock();
}
}
int main()
{
object = new Object();
thread th(do_something);
th.detach();
Sleep(1000);
mu.lock(); // or const std::lock_guard<std::mutex> lock(mu); and get rid of unlock
delete object;
object = nullptr;
mu.unlock();
return 0;
}
Alternatively, as you don't have to share data between thread, you might do:
int main()
{
Object object;
thread th(do_something);
Sleep(1000);
th.join();
return 0;
}
and get rid of all mutex
Have a look at this, it shows the use of scoped_lock, std::async and managment of lifecycles through scopes (demo here : https://onlinegdb.com/FDw9fG9rS)
#include <future>
#include <mutex>
#include <chrono>
#include <iostream>
// using namespace std; <== dont do this
// mutex mu; avoid global variables.
class Object
{
public:
Object() :
m_var{ 1 }
{
}
~Object()
{
}
void do_something()
{
using namespace std::chrono_literals;
for(std::size_t n = 0; n < 30; ++n)
{
// extra scope to reduce time of the lock
{
std::scoped_lock<std::mutex> lock{ m_mtx };
m_var++;
std::cout << ".";
}
std::this_thread::sleep_for(150ms);
}
}
private:
std::mutex m_mtx;
char m_var;
};
int main()
{
Object object;
// extra scope to manage lifecycle of future
{
// use a lambda function to start the member function of object
auto future = std::async(std::launch::async, [&] {object.do_something(); });
std::cout << "do something started\n";
// destructor of future will synchronize with end of thread;
}
std::cout << "\n work done\n";
// safe to go out of scope now and destroy the object
return 0;
}
All you assumed and asked in your question is right. The variable will always be freed.
But your code has one big problem. Lets look at your example:
int main()
{
object = new Object();
thread th(do_something);
th.detach();
Sleep(1000);
delete object;
object = nullptr;
return 0;
}
You create a thread that will call do_something(). But lets just assume that right after the thread creation the kernel interrupts the thread and does something else, like updating the stackoverflow tab in your web browser with this answer. So do_something() isn't called yet and won't be for a while since we all know how slow browsers are.
Meanwhile the main function sleeps 1 second and then calls delete object;. That calls Object::~Object(), which acquires the mutex and deletes the var and releases the mutex and finally frees the object.
Now assume that right at this point the kernel interrupts the main thread and schedules the other thread. object still has the address of the object that was deleted. So your other thread will acquire the mutex, object is not nullptr so it accesses it and BOOM.
PS: object isn't atomic so calling object = nullptr in main() will also race with if (object).

Can multi threads access same weak_ptr object C++

So I have this class:
class Test
{
...
std::weak_ptr<W> m_w;
std::thread t1;
std::thread t2;
public:
Test (const std::shared_ptr<W> w);
void t1Task();
void t2Task();
...
}
In its constructor, pretty regular, they are initialized:
...
m_w(w),
...
t1 = std::thread (&Test::t1Task, this);
t2 = std::thread (&Test::t2Task, this);
So here comes my question, can I use lock() in these 2 task functions considering they start at the same time like I do in the code below? If I can't, what can I do since I have to get a shared_ptr to w object in both threads?
void Test::t1Task ( )
{
std::shared_ptr<W> wPtr = m_w.lock(); // 1st line of this func
while(/*some condition*/)
{
// going to use wPtr in this while loop
}
}
void Test::t2Task()
{
std::shared_ptr<W> wPtr = m_w.lock(); // 1st line of this func
while(/*some condition*/)
{
// going to use wPtr in this while loop
}
}
There is no issue calling lock. lock isn't like lock on a mutex where it blocks all other threads. What it does do is effectively lock you into the ownership of the pointer if there is still a valid shared_ptr some where in your code at that time.
That means the only thing you need to do is check if wPtr is not equal to nullptr before you use it since lock could return a null shared_ptr.
Do note that this does not provide any thread safety guarantee about the object pointed to by the pointer. You still have to make sure you access that in a thread safe manner. Without knowing what you are doing I can't say if your loops are actualy safe.

How to use mutex correctly as parameter for a memberfunction in a thread?

My Problem is that I dont know how to properly use the mutex. I understand how it works theoretically but I don´t know why it doesnt work in my code.I thought if I use a mutex on a var it will be blocked until it gets unlocked. Nevertheless it seems I still have a data race.
I tried to define a class mutex and a mutex in the main which I pass by reference. Somehow nothing of this works.
class test {
public:
void dosmth(std::mutex &a);
int getT(){return t;};
private:
int t = 0;
};
void test::dosmth(std::mutex &a) {
for(;;){
a.lock();
t++;
if(t==1000){
t=0;
}
a.unlock();
}
}
int main() {
test te;
std::mutex help;
std::thread t(&test::dosmth, std::addressof(te), std::ref(help));
for(;;){
for (int i = 0; i <te.getT() ; ++i) {
std::cout<<te.getT()<<std::endl;
}
}
}
The result just should be that I get some output so I will now it works.
As Michael mentioned, you should synchronise the reader and writer to avoid undefined behaviour. Instead of passing the mutex as an argument, a common pattern is to make the mutex a member of the object (te), lock and unlock every time (prefer lock_gaurd instead of manually locking and unlocking) you enter a member function (that modifies internal state of the object). Here is some pseudo-code:
class Foo{
std::mutex m; // reader and writer are sync'ed on the same mutex
int data_to_sync;
public:
int read(){
lock_gaurd<mutex> lg(m); //RAII lock
return data_to_sync;
//automagically released upon exit
}
void write(){
lock_gaurd<mutex> lg(m);
data_to_sync++;
}
};
A mutex can only guarantee mutual exclusion if said mutex is used to regulate entry to all critical sections of code where a given object would be accessed concurrently. In your case, you have your second thread modify the value of the object te.t while your main thread is reading the value of the same object. Only one thread, however, is using a mutex to protect the access to te.t. The object te.t is not atomic. Therefore, you have a data race and, thus, undefined behavior [intro.races]/21.
You have to also lock and unlock the mutex in your for(;;) loop in main, e.g.:
for(;;){
help.lock();
for (int i = 0; i <te.getT() ; ++i) {
std::cout<<te.getT()<<std::endl;
}
help.unlock();
}
or better, using std::lock_guard:
for(;;){
std::lock_guard lock(help);
for (int i = 0; i <te.getT() ; ++i) {
std::cout<<te.getT()<<std::endl;
}
}
I thought if I use a mutex on a var...
You don't use a mutex "on a var." Locking a mutex prevents other threads from locking the same mutex at the same time, but it does not stop other threads from accessing any particular variable(s).
If you want to use a mutex to protect a variable (or more typically, several variables) from being accessed by more than one thread at the same time, then it's up to you to ensure that you do not write any code that accesses the variables without locking the mutex first.

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.