Thread safe access to member variable - c++

So I have a class which spawns a thread with the class object as parameter. Then in the thread I call a member function. I use Critical_Sections for synchronizing.
So would that implementation be thread safe? Because only the member is thread safe and not the class object.
class TestThread : public CThread
{
public:
virtual DWORD Work(void* pData) // Thread function
{
while (true)
{
if (Closing())
{
printf("Closing thread");
return 0;
}
Lock(); //EnterCritical
threadSafeVar++;
UnLock(); //LeaveCritical
}
}
int GetCounter()
{
int tmp;
Lock(); //EnterCritical
tmp = threadSafeVar;
UnLock(); //LeaveCritical
return tmp;
}
private:
int threadSafeVar;
};
.
.
.
TestThread thr;
thr.Run();
while (true)
{
printf("%d\n",thr.GetCounter());
}

If the member is your critical section you should only lock the access to it.
BTW, You can implement a Locker like:
class Locker
{
mutex &m_;
public:
Locker(mutex &m) : m_(m)
{
m.acquire();
}
~Locker()
{
m_.release();
}
};
And your code would look like:
mutex myVarMutex;
...
{
Locker lock(myVarMutex);
threadSafeVar++;
}
...
int GetCounter()
{
Locker lock(myVarMutex);
return threadSafeVar;
}

Your implementation is thread safe because you have protected with mutex your access to attribute.
Here, your class is a thread, so your object is a thread. It's what you do in your thread that tell if it is thread safe.
You get your value with a lock/unlock system and you write it with the same system. So your function is thread safe.

Related

Thread safety of nested calls

I have two libs, one is thread safe called class A, The other lib called class B, which used class A to realize functions.
class A {
public:
void Get() {
std::lock_guard<std::mutex> lock(mutex_);
do_something
}
void Put() {
std::lock_guard<std::mutex> lock(mutex_);
do_something
}
private:
std::mutex mutex_;
};
class B {
public:
void Get() {
a.Get();
}
void Put() {
a.Put();
}
private:
A a;
};
So is class B thread safe?
I know that judging whether the thread is safe depends on whether the operation is atomic. If the put operate is not atomic then it's not thread safe. According to the above requirements, I think class B is not an atomic operation, so it is not thread-safe?
When the operation is not atomic, it may not be thread safe. for example we add some operate like below, Is it right?
class B {
public:
void Get() { // But Get is not atomic!!!
do_some_thing(); // atomic
a.Get(); // atomic
do_some_thing(); // atomic
}
void Put() {
do_some_thing();
a.Put();
do_some_thing();
}
private:
A a;
};
Thread safety concerns about the race conditions and data races.
Now, Since the methods of class B don't use any data directly but via delegating other methods in class A that as you said are thread-safe, the methods in B are thread-safe.

Passing mutex reference from main to a class

I need to work with the same mutex and unique_lock across the main function and class instances. However, I am having trouble assigning the mutex/unique_lock address to a class member variable (that is a mutex&).
This is what I have:
Worker.h
class Worker
{
private:
std::mutex &m_mu;
std::unique_lock<std::mutex> &locker;
public:
void start(std::mutex &mu, std::unique_lock<std::mutex> &locker);
};
Worker.cpp
void Worker::start(std::mutex &mu, std::unique_lock<std::mutex> &locker)
{
this->mu = mu; // error
this->locker = locker; // error
}
I tried doing this->mu(mu); but that doesn't work either. Is there anything I can do to make this work?
Thanks.
You need to pass the mutex reference when you construct your class.
Worker::Worker(std::mutex &mu, std::unique_lock<std::mutex> &locker)
:m_mu(mu), locker(locker)
{}
That's the only place you can initialize a reference. Once it's constructed, you cannot change what it references.
Why do you need the locker? The mutex makes the synchronization, the lock is just a RAII object to ease acquiring the mutex.
You don't need to pass the lock object to the function. As long as the class is referring to the correct mutex you can lock the mutex inside the function like this:
class Worker
{
private:
std::mutex& m_mu;
public:
Worker(std::mutex& mu): m_mu(mu) {} // bind reference during initialization
void start();
};
// Worker.cpp
void Worker::start()
{
std::unique_lock<std::mutex> locker(m_mu); // lock the shared resource
// Do something with it here
}
int main()
{
std::mutex mu;
std::vector<Worker> workers(4, Worker(std::ref(mu)));
// etc...
}

How to terminate a std::thread?

I am currently developing a program that needs to download some images from the socket server,and the downloading work will execute a long time. So, I create a new std::thread to do that.
Once it's downloaded,the std::thread will call a member function of current Class, but this Class is likely to have been released. So, I got a exception.
How to solve this problem?
void xxx::fun1()
{
...
}
void xxx::downloadImg()
{
...a long time
if(downloadComplete)
{
this->fun1();
}
}
void xxx::mainProcees()
{
std::thread* th = new thread(mem_fn(&xxx::downloadImg),this);
th->detach();
//if I use th->join(),the UI will be obstructed
}
Don't detach the thread. Instead, you can have a data member that hold a pointer to the thread, and join the thread in destructor.
class YourClass {
public:
~YourClass() {
if (_thread != nullptr) {
_thread->join();
delete _thread;
}
}
void mainProcees() {
_thread = new thread(&YourClass::downloadImg,this);
}
private:
thread *_thread = nullptr;
};
UPDATE
Just as #milleniumbug pointed out, you don't need dynamic allocation for the thread object, since it is movable. So the other solution is as follows.
class YourClass {
public:
~YourClass() {
if (_thread.joinable())
_thread.join();
}
void mainProcess() {
_thread = std::thread(&YourClass::downloadImg, this);
}
private:
std::thread _thread;
};

understanding std::thread semantic with worker function as class member

To implement the logic when contructed object starts background thread for real work, I'm using a pattern like this (simplified):
class A {
std::thread t{&A::run, this};
std::atomic_bool done;
// variables are the question about
std::vector<std::thread> array_for_thread_management;
// ... and other members
protected:
void run() {
...
array_for_thread_management.push_back([](){...});
...
}
public:
A() = default;
// all other constructors deleted because of used
// some members like std::atomic_bool done;
~A() {
done = true;
bi::named_condition cnd{bi::open_only, "cnd"};
cnd.notify_one();
if (t.joinable())
t.join();
for(std::thread& worker : array_for_thread_management) {
if (worker.joinable()) worker.join();
}
}
};
If I'm adding a push of child threads in primary background thread into a vector in run() member, the object hangs on destructor.
even there is no real threads in a vector, just started this without connections from outside and try to stop this by destructor
Of course, once you have this pointer in your run method, you can access class members via this pointer. I guess the problem with your code is that the thread is spawned before any other members are initialized, as it is the first member in your class definition. I suspect with the following definition of class A you'll have no problems with accessing member variables:
class A {
std::atomic_bool done;
// variables are the question about
int i;
std::string s;
std::vector<std::string> v;
// and only after everything above is initialized:
std::thread t{&A::run, this}; // spawn a thread
// ...
}
However, personally I would prefer having a separate method start() which spawns a thread to spawning it inside class constructor implicitly. It may look like this:
class A
{
std::unique_ptr<std::thread> t;
std::atomic<bool> some_flag;
public:
void start()
{
t.reset(new std::thread(&A::run, this));
}
private:
void run()
{
some_flag.store(true);
}
};

boost-threads: How can I pass a scoped_lock to a callee?

I'm new to the boost threads library. I have a situation where I acquire a scoped_lock in one function and need to wait on it in a callee.
The code is on the lines of:
class HavingMutex
{
public:
...
private:
static boost::mutex m;
static boost::condition_variable *c;
static void a();
static void b();
static void d();
}
void HavingMutex::a()
{
boost::mutex::scoped_lock lock(m);
...
b() //Need to pass lock here. Dunno how !
}
void HavingMutex::b(lock)
{
if (some condition)
d(lock) // Need to pass lock here. How ?
}
void HavingMutex::d(//Need to get lock here)
{
c->wait(lock); //Need to pass lock here (doesn't allow direct passing of mutex m)
}
Basically, in function d(), I need to access the scoped lock I acquired in a() so that I can wait on it. How do I do that ? (Some other thread will notify).
Or can I directly wait on a mutex instead of a lock ?
Any help is appreciated. Thanks !
Pass it by reference:
void HavingMutex::d(boost::mutex::scoped_lock & lock)
{ // ^ that means "reference"
c->wait(lock);
}