After asking a question about mutexes here, I was warned about deadlocks.
Would the example I put together below be a reasonable way to avoid deadlocks?
class Foo
{
public:
Foo();
void Thread();
int GetWidgetProperty();
int GetGadgetProperty();
private:
Widget widget_;
Gadget gadget_;
VDK::MutexID widgetLock;
VDK::MutexID gadgetLock;
};
Foo::Foo()
: widget_(42)
, gadget_(widget_)
{
widgetLock = VDK::CreateMutex();
gadgetLock = VDK::CreateMutex();
}
void Foo::Thread()
{
while(1)
{
VDK::AcquireMutex(widgetLock);
// Use widget
VDK::ReleaseMutex(widgetLock);
VDK::AcquireMutex(widgetLock);
VDK::AcquireMutex(gadgetLock);
// use gadget
VDK::ReleaseMutex(widgetLock);
VDK::ReleaseMutex(gadgetLock);
}
}
int Foo::GetWidgetProperty()
{
VDK::AcquireMutex(widgetLock);
return widget_.GetProp();
VDK::ReleaseMutex(widgetLock);
}
int Foo::GetGadgetProperty()
{
VDK::AcquireMutex(widgetLock);
VDK::AcquireMutex(gadgetLock);
return gadget.GetProp();
VDK::ReleaseMutex(widgetLock);
VDK::ReleaseMutex(gadgetLock);
}
Since the call GetGadgetProperty could result in using the widget, I'm guessing we also need to protect our self with a lock here. My question is, am I requiring and releasing them in the right order?
Your code has obvious deadlock. You can't release mutex after return statement. Whats more it's better to unlock them in reverse (to locking) order. Proper code should look like this:
int Foo::GetWidgetProperty()
{
VDK::AcquireMutex(widgetLock);
int ret = widget_.GetProp();
VDK::ReleaseMutex(widgetLock);
return ret;
}
int Foo::GetGadgetProperty()
{
VDK::AcquireMutex(widgetLock);
VDK::AcquireMutex(gadgetLock);
int ret = gadget.GetProp();
VDK::ReleaseMutex(gadgetLock);
VDK::ReleaseMutex(widgetLock);
return ret;
}
An even better way would be to rely on RAII to do the job for you.
I invite you to read about std::lock_guard. The basic principle is that you acquire the mutex by declaring an object. And the mutex is released automatically at the end of its lifetime.
Now, you can use block scopes for the region of code that needs to lock a mutex that way:
{
std::lock_guard lockWidget{widgetMutex};//Acquire widget mutex
std::lock_guard lockGadget{gadgetMutex};//Acquire gadget mutex
//do stuff with widget/gadget
//...
//As the lock_guards go out of scope in the reverse order of
//declaration, the mutexes are released
}
Of course, this works with the standard library mutexes, so you'd have to adapt to your use.
That would prevent error such as trying to release a mutex after a return statement, which obviously will never happen, or in the face of exception that would happen before you actually release the mutex.
Related
In C++20 std::jthread was introduced as a safer version of std::thread; where std::jthread, as far as I understand, cleans up after itself when the thread exits.
Also, the concept of cooperative cancellation is introduced such that an std::jthread manages an std::stop_source that handles the state of the underlying thread, this std::stop_source exposes an std::stop_token that outsiders can use to read the state of the thread sanely.
What I have is something like this.
class foo {
std::stop_token stok;
std::stop_source ssource;
public:
void start_foo() {
// ...
auto calculation = [this](std::stop_token inner_tok) {
// ... (*this is used here)
while(!inner_tok.stop_requested()) {
// stuff
}
}
auto thread = std::jthread(calculation);
ctok = thread.get_stop_token();
ssource = thread.get_stop_source();
thread.detach(); // ??
}
void stop_foo() {
if (ssource.stop_possible()) {
ssource.request_stop();
}
}
~foo() {
stop_foo();
}
}
Note foo is managed by a std::shared_ptr, and there is no public constructor.
Somewhere along the line, another thread can call foo::stop_foo() on a possibly detached thread.
Is what I am doing safe?
Also, when detaching a thread, the C++ handle is no longer associated with the running thread, and the OS manages it, but does the thread keep receiving stop notifications from the std::stop_source?
Is there a better way to achieve what I need? In MVSC, this doesn't seem to raise any exceptions or halt program execution, and I've done a lot of testing to verify this.
So, is this solution portable?
What you wrote is potentially unsafe if the thread accesses this after the foo has been destroyed. It's also a bit convoluted. A simpler approach would just be to stick the jthread in the structure...
class foo {
std::jthread thr;
public:
void start_foo() {
// ...
jthr = std::jthread([this](std::stop_token inner_tok) {
// ... (*this is used here)
while(!inner_tok.stop_requested()) {
// stuff
}
});
}
void stop_foo() {
jthr.request_stop();
}
~foo() {
stop_foo();
// jthr.detatch(); // this is a bad idea
}
}
To match the semantics of your code, you would uncomment the jthr.detach() in the destructor, but this is actually a bad idea since then you could end up destroying foo while the thread is still accessing it. The code I wrote above is safe, but obviously whichever thread drops the last reference to the foo will have to wait for the jthread to exit. If that's really intolerable, then maybe you want to change the API to stick a shared_ptr in the thread itself, so that the thread can destroy foo if it is still running after the last external reference is dropped.
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.
I have some fear about using unique_ptr with multithreading without mutex. I wrote simplified code below, please take a look. If I check unique_ptr != nullptr, is it thread safe?
class BigClassCreatedOnce
{
public:
std::atomic<bool> var;
// A lot of other stuff
};
BigClassCreatedOnce class instance will be created only once but I'm not sure is it safe to use it between threads.
class MainClass
{
public:
// m_bigClass used all around the class from the Main Thread
MainClass()
: m_bigClass()
, m_thread()
{
m_thread = std::thread([this]() {
while (1)
{
methodToBeCalledFromThread();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
});
// other stuff here
m_bigClass.reset(new BigClassCreatedOnce()); // created only once
}
void methodToBeCalledFromThread()
{
if (!m_bigClass) // As I understand this is not safe
{
return;
}
if (m_bigClass->var.load()) // As I understand this is safe
{
// does something
}
}
std::unique_ptr<BigClassCreatedOnce> m_bigClass;
std::thread m_thread;
};
I just put it into infinity loop to simplify the sample.
int main()
{
MainClass ms;
while (1)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
If I check unique_ptr != nullptr, is it thread safe
No, it is not thread safe. If you have more than one thread and at least of one of them writes to the shared data then you need synchronization. If you do not then you have a data race and it is undefined behavior.
m_bigClass.reset(new BigClassCreatedOnce()); // created only once
and
if (!m_bigClass)
Can both happen at the same time, so it is a data race.
I would also like to point out that
if (m_bigClass->var.load())
Is also not thread safe. var.load() is, but the access of m_bigClass is not so you could also have a data race there.
Using MS Visual C++2012
A class has a member of type std::atomic_flag
class A {
public:
...
std::atomic_flag lockFlag;
A () { std::atomic_flag_clear (&lockFlag); }
};
There is an object of type A
A object;
who can be accessed by two (Boost) threads
void thr1(A* objPtr) { ... }
void thr2(A* objPtr) { ... }
The idea is wait the thread if the object is being accessed by the other thread.
The question is: do it is possible construct such mechanism with an atomic_flag object? Not to say that for the moment, I want some lightweight that a boost::mutex.
By the way the process involved in one of the threads is very long query to a dBase who get many rows, and I only need suspend it in a certain zone of code where the collision occurs (when processing each row) and I can't wait the entire thread to finish join().
I've tryed in each thread some as:
thr1 (A* objPtr) {
...
while (std::atomic_flag_test_and_set_explicit (&objPtr->lockFlag, std::memory_order_acquire)) {
boost::this_thread::sleep(boost::posix_time::millisec(100));
}
... /* Zone to portect */
std::atomic_flag_clear_explicit (&objPtr->lockFlag, std::memory_order_release);
... /* the process continues */
}
But with no success, because the second thread hangs. In fact, I don't completely understand the mechanism involved in the atomic_flag_test_and_set_explicit function. Neither if such function returns inmediately or can delay until the flag can be locked.
Also it is a mistery to me how to get a lock mechanism with such a function who always set the value, and return the previous value. with no option to only read the actual setting.
Any suggestion are welcome.
By the way the process involved in one of the threads is very long query to a dBase who get many rows, and I only need suspend it in a certain zone of code where the collision occurs (when processing each row) and I can't wait the entire thread to finish join().
Such a zone is known as the critical section. The simplest way to work with a critical section is to lock by mutual exclusion.
The mutex solution suggested is indeed the way to go, unless you can prove that this is a hotspot and the lock contention is a performance problem. Lock-free programming using just atomic and intrinsics is enormously complex and cannot be recommended at this level.
Here's a simple example showing how you could do this (live on http://liveworkspace.org/code/6af945eda5132a5221db823fa6bde49a):
#include <iostream>
#include <thread>
#include <mutex>
struct A
{
std::mutex mux;
int x;
A() : x(0) {}
};
void threadf(A* data)
{
for(int i=0; i<10; ++i)
{
std::lock_guard<std::mutex> lock(data->mux);
data->x++;
}
}
int main(int argc, const char *argv[])
{
A instance;
auto t1 = std::thread(threadf, &instance);
auto t2 = std::thread(threadf, &instance);
t1.join();
t2.join();
std::cout << instance.x << std::endl;
return 0;
}
It looks like you're trying to write a spinlock. Yes, you can do that with std::atomic_flag, but you are better off using std::mutex instead. Don't use atomics unless you really know what you're doing.
To actually answer the question asked: Yes, you can use std::atomic_flag to create a thread locking object called a spinlock.
#include <atomic>
class atomic_lock
{
public:
atomic_lock()
: lock_( ATOMIC_FLAG_INIT )
{}
void lock()
{
while ( lock_.test_and_set() ) { } // Spin until the lock is acquired.
}
void unlock()
{
lock_.clear();
}
private:
std::atomic_flag lock_;
};
I want to have a thread wait for the destruction of a specific object by another thread. I thought about implementing it somehow like this:
class Foo {
private:
pthread_mutex_t* mutex;
pthread_cond_t* condition;
public:
Foo(pthread_mutex_t* _mutex, pthread_cond_t* _condition) : mutex(_mutex), condition(_condition) {}
void waitForDestruction(void) {
pthread_mutex_lock(mutex);
pthread_cond_wait(condition,mutex);
pthread_mutex_unlock(mutex);
}
~Foo(void) {
pthread_mutex_lock(mutex);
pthread_cond_signal(condition);
pthread_mutex_unlock(mutex);
}
};
I know, however, that i must handle spurious wakeups in the waitForDestruction method, but i can't call anything on 'this', because it could already be destructed.
Another possibility that crossed my mind was to not use a condition variable, but lock the mutex in the constructor, unlock it in the destructor and lock/unlock it in the waitForDestruction method - this should work with a non-recursive mutex, and iirc i can unlock a mutex from a thread which didn't lock it, right? Will the second option suffer from any spurious wakeups?
It is always a difficult matter. But how about these lines of code:
struct FooSync {
typedef boost::shared_ptr<FooSync> Ptr;
FooSync() : owner(boost::this_thread::get_id()) {
}
void Wait() {
assert(boost::this_thread::get_id() != owner);
mutex.lock();
mutex.unlock();
}
boost::mutex mutex;
boost::thread::id owner;
};
struct Foo {
Foo() { }
~Foo() {
for (size_t i = 0; i < waiters.size(); ++i) {
waiters[i]->mutex.unlock();
}
}
FooSync::Ptr GetSync() {
waiters.push_back(FooSync::Ptr(new FooSync));
waiters.back()->mutex.lock();
return waiters.back();
}
std::vector<FooSync::Ptr> waiters;
};
The solution above would allow any number of destruction-wait object on a single Foo object. As long as it will correctly manage memory occupied by these objects. It seems that nothing prevents Foo instances to be created on the stack.
Though the only drawback I see is that it requires that destruction-wait objects always created in a thread that "owns" Foo object instance otherwise the recursive lock will probably happen. There is more, if GetSync gets called from multiple threads race condition may occur after push_back.
EDIT:
Ok, i have reconsidered the problem and came up with new solution. Take a look:
typedef boost::shared_ptr<boost::shared_mutex> MutexPtr;
struct FooSync {
typedef boost::shared_ptr<FooSync> Ptr;
FooSync(MutexPtr const& ptr) : mutex(ptr) {
}
void Wait() {
mutex->lock_shared();
mutex->unlock_shared();
}
MutexPtr mutex;
};
struct Foo {
Foo() : mutex(new boost::shared_mutex) {
mutex->lock();
}
~Foo() {
mutex->unlock();
}
FooSync::Ptr GetSync() {
return FooSync::Ptr(new FooSync(mutex));
}
MutexPtr mutex;
};
Now it seems reasonably cleaner and much less points of code are subjects to race conditions. There is only one synchronization primitive shared between object itself and all the sync-objects. Some efforts must be taken to overcome the case when Wait called in the thread where the object itself is (like in my first example). If the target platform does not support shared_mutex it is ok to go along with good-ol mutex. shared_mutex seems to reduce the burden of locks when there are many of FooSyncs waiting.