C++ Thread access issue with class member variables - c++

After using threads for a while, I got into a situation where I needed a thread to run forever until a a function (or any sort of event) was called. To do this I created a bool value to control a while loop inside the function that was executed by the thread, but I quickly noticed that external variables are not updated after a thread starts running, causing the thread to never stop when it was asked to.
Heres some simple code to represent the issue:
#include <cstdio>
#include <thread>
#include <chrono>
class A {
public:
A();
void startThread();
void endThread();
private:
void threadCall();
bool active;
};
int main() {
A threadThing;
threadThing.startThread();
printf("[M] Thread Created\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
threadThing.endThread();
printf("[M] Thread Killed\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
A::A() {
active = false;
}
void A::startThread() {
active = true;
std::thread AThread(&A::threadCall, *this);
AThread.detach();
}
void A::endThread() {
active = false;
}
void A::threadCall() {
printf("[T] Thread Started\n");
while (active) {
std::this_thread::sleep_for(std::chrono::seconds(2));
}
printf("[T] Thread Ended\n");
}
The expected result of this would be that the main function starts the thread, the thread says it started, then 4 seconds later the thread is killed and the thread says it ended, when in reality the thread never says it ends. Is there a way to let the thread access the 'active' variable, or is my approach to this problem incorrect altogether? (Side note, I did try to figure this out on my own but only got stuff like local thread storage which seems like its only for storage inside of threads, not access to the outside but I could be wrong)

The problem is with the constructor of std::thread, it copies/moves by default.
std::thread AThread(&A::threadCall, *this);
this copies the object into the new thread, so checking the active variable in the new object has no effect.
you can remove the *
std::thread AThread(&A::threadCall, this);
you pass the object pointer into the new thread, it will call like the method like this(*this).threadCall().
Edit: as the comments say, this is not guarantee to be thread safe, you need to use std::atomic<bool> to be safe.

What you need to do is pass an A class pointer as an argument to your function that is your thread.
void A::startThread()
{
active = true;
std::thread AThread(threadCall, this);
AThread.detach();
}
void A::threadCall(A *aClass)
{
printf("[T] Thread Started\n");
while (aClass->active)
{
std::this_thread::sleep_for(std::chrono::seconds(2));
}
printf("[T] Thread Ended\n");
}

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

Calling detach() at the end of the thread

I have a working thread similar to the following code. In begin_work, it will check whether the working thread is executing before creating a new working thread. However, begin_work will never create the next working thread when the current thread is exited until I call end_work.
I have tried to call detach at the end of the thread and it works fine. Is it safe to call detach at the end of the thread? Or, how can I do to safely create the next working thread without calling end_work before calling begin_work?
class thread_worker {
private:
std::thread worker;
// ... other menbers
public:
thread_worker() {};
~thread_worker() { end_work(); };
void begin_work() {
if (!worker.joinable()) {
worker = std::thread { &thread_worker::do_work, this };
}
}
void do_work() {
// ... access other members ...
if (exit not by notify) {
worker.detach(); // can I call detach?
}
}
void end_work() {
if (worker.joinable()) {
// notify worker to exit
worker.join();
}
}
};
Edit:
My purpose is to call begin_work without block. If there is one working thread on execution, then the function will return directly or returns an is_working error. Otherwise, create a new working thread seamlessly.
Since std::thread::joinable() always returns true until join or detach is called. As a result, the future call of begin_work will never create the new working thread even though the current working thread has exited.
Therefore, I need a mechanism to automatically detach at the end of the thread.
I have tried to call detach at the end of the thread and it works fine
There's data race in the access to worker - it's undefined behaviour. When begin_work tests worker.joinable(), do_work might be detaching it at the same time (the call to worker.detach()).
You can instead detach the immediately when creating it:
worker = std::thread { &thread_worker::do_work, this };
worker.detach();
However, this can leave multiple threads running at the same time, which contradicts your requirement of running one worker thread at a time (but why only one? that just makes threading pointless).
Instead you can do:
void begin_work() {
end_work();
worker = std::thread { &thread_worker::do_work, this };
}
which ensures the previous thread completed.
Based on yuor edit, you only need to check whether you can join without wait - that seems to be reason you want to detach. You can instead do that with an atomic flag. Basically, you just to take care of the data race noted above.
class thread_worker {
private:
std::thread worker;
std::atomic_bool w_done {true};
// ... other menbers
public:
thread_worker() {};
~thread_worker() { end_work(); };
void begin_work() {
if (w_done) {
end_work();
worker = std::thread { &thread_worker::do_work, this };
}
}
void do_work() {
// ... access other members ...
w_done = true;
}
void end_work() {
w_done = false;
if (worker.joinable()) {
// notify worker to exit
worker.join();
}
}
};

Cannot kill std::thread

I have a program that I need to run a thread in. The problem is whenever I try to kill this thread from either inside the thread or outside the thread I get a "error 6 - invalid handle" error
class myclass
{
public:
static myclass* inst()
{
if (oInst == nullptr) oInst = new myclass;
return oInst;
};
void main();
void start();
void ex_stop()
{
//HANDLE Stopper = Killer.native_handle();
//TerminateThread(Stopper, 0);
}
}
private:
std::thread Killer;
}
void myclass::start()
{
Killer = std::thread(&myclass::ex_main, this);
Killer.detach();
}
void myclass::main()
{
...
if (0 == TerminateThread(Killer.native_handle(), 0))
{
char error[200];
sprintf(error, "error %i\n", GetLastError());
printf(error);
}
This is how I start the class/thread
myclass::inst()->start();
I've also tried making std::thread Killer an extern and declaring it in my .cpp and .h files, this way I can access it from outside the class, but I still get the same "error 6, invalid thread handle" error.
Can someone please tell me what's wrong with this code? Thanks
The usual way of having a worker thread set up is to put it into a loop, and on each loop check to see if a boolean atomic has been changed ... something that would look like (but this probably doesn't compile straight off; the threadMain will probably need binding)
class myThreadJob {
public:
myThreadJob():
doRun(true),
thread(threadMain)
{}
void threadMain() {
while (doRun) {...}
}
void stop() {
doRun = false;
thread.join();
}
private:
std::atomic<bool> doRun;
std::thread thread;
}
You've not said if your thread is a will do many tasks in a queue, or if it's a one off job that it's doing, but in any case if it's expected to be a long lived thread, it should check periodically that it can still run.
Because you've called detach() on your thread, your thread is no longer associated with your process. You can think of detach() as a declaration that the thread does not need anything local to the creating thread.
You are not allowed to join it; and you're expecting it to run to termination.

std::thread::join blocks indefinitely out of main

std::thread::join does not return, even if the thread routine is exited.
Guess, I have a class.
class A
{
public:
A()
{
this->thr = std::thread(&A::foo, this);
}
~A()
{
this->join();
}
void join()
{
this->cond.notify_all();
if (this->thr.joinable())
{
this->thr.join();
}
}
private:
void foo()
{
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
this->cond.wait(lck);
MessageBox(L"I'm done!");
}
private:
std::thread thr;
std::condition_variable cond;
};
My application contains the only instance of A. It is a global variable.
If A::join is called from the destructor, std::thread::join blocks forever.
If I call A::join manually (e.g. before exiting main), everything is alright.
My main looks like this:
A a;
int main()
{
auto timeout = std::chrono::seconds(3);
std::this_thread::sleep_for(timeout);
// a.join();
}
By the way, MessageBox is always executed.
Is that the same problem as here?
Yes it is the same bug as in the referenced link since your example also hangs on _Thrd_join. You could be interrested in this question which contains a far more detailed analysis.
from your comment
"It doesn't seem to be a great solution. I works, but what if the main
is not so trivial? There're a lot of different ways of exiting from my
application. Thus, I've got to join my threads manually every time I
need it?"
how about making A a std::unique_ptr within your main. that way, no matter how your main exits, it'll always destroy A before exiting main() and you won't have this problem.

Deleting boost::thread descendant

I am trying to write a class that would run a thread upon its object creation and stop the thread once the object gets deleted.
class MyThread : public boost::thread {
public:
MyThread() : bAlive(true) {
boost::thread(&MyThread::ThreadFunction,this);
}
~MyThread() {
{
boost::unique_lock<boost::mutex> lock(Mutex);
bAlive=false;
}
ConditionVariable.notify_one();
join();
}
private:
volatile bool bAlive;
boost::mutex Mutex;
boost::condition_variable ConditionVariable;
void ThreadFunction() {
boost::unique_lock<boost::mutex> lock(Mutex);
while(bAlive) {
ConditionVariable.timed_wait(lock,boost::get_system_time()+ boost::posix_time::milliseconds(MAX_IDLE));
/*******************************************
* Here goes some code executed by a thread *
*******************************************/
}
}
};
Theoretically, I want to wake the thread up instantly as soon as it needs to be finished, so I had to use timed_wait instead of Sleep.
This works fine until I try to delete an object of this class. In most cases, it deletes normally, but occasionally it causes an error either in condition_variable.hpp, thread_primitives.hpp or crtexe.c. Sometimes I am notified that "Free Heap block 3da7a8 modified at 3da804 after it was freed", and sometimes I'm not. And yes, I'm aware of the spurious wakeups of timed_wait, in this case it's not critical.
Can you please point me to the source of my problem? What am I doing wrong?
I see what you're trying to do but it doesn't work as you expect:
MyThread foo;
default constructs a boost::thread (because MyThread is derived from boost::thread).
The default constructor creates a boost::thread instance that refers to Not-a-Thread.
MyThread() {
boost::thread(&MyThread::ThreadFunction,this);
}
is actually creating a different thread and you're ignoring the returned object (the valid thread).
~MyThread() {
// ...
join();
}
is then trying to join the default constructed thread (which throws an exception inside the destructor) and you never join the thread that actually does the work.
First of all, don't derive from boost::thread. Create a member variable instead:
class MyThread {
// ...
private:
// ...
boost::thread _thread;
};
In the constructor, create and assign a thread to that member variable:
MyThread() {
_thread = boost::thread(&MyThread::ThreadFunction,this);
}
and call its join() in your destructor.
~MyThread() {
// ...
_thread.join();
}
That should fix your problem.
However, if you simply want to exit the thread when your object is destroyed (and don't have to wake it up while its running), you can use a different approach. Remove the mutex and the condition variable and use interrupt instead. This will cause sleep() to throw an exception so you have to catch it:
void ThreadFunction() {
try {
for(;;) {
boost::this_thread::sleep(boost::posix_time::milliseconds(MAX_IDLE));
// Here goes some code executed by a thread
}
} catch( const boost::thread_interrupted& e ) {
// ignore exception: thread interrupted, exit function
}
}
This will instantly exit the ThreadFunction when the thread is interrupted. If you don't need the thread to sleep every cycle, you can replace it with boost::this_thread::interruption_point(). This will just throw an exception if the thread is interrupted.
Now you can simply interrupt the thread in the destructor:
MyThread::~MyThread() {
_thread.interrupt();
_thread.join();
}