Thread Safety Of a single variable - c++

I understand the concept of thread safety. I am looking for advice to simplify thread safety when trying to protect a single variable.
Say I have a variable:
double aPass;
and I want to protect this variable, so i create a mutex:
pthread_mutex_t aPass_lock;
Now there are two good ways i can think of doing this but they both have annoying disadvantages. The first is to make a thread safe class to hold the variable:
class aPass {
public:
aPass() {
pthread_mutex_init(&aPass_lock, NULL);
aPass_ = 0;
}
void get(double & setMe) {
pthread_mutex_lock(aPass_lock);
setMe = aPass_
pthread_mutex_unlock(aPass_lock);
}
void set(const double setThis) {
pthread_mutex_lock(aPass_lock);
aPass_ = setThis;
pthread_mutex_unlock(aPass_lock);
}
private:
double aPass_;
pthread_mutex_t aPass_lock;
};
Now this will keep aPass totally safe, nothing can be mistaken and ever touch it, YAY! however look at all that mess and imagine the confusion when accessing it. gross.
The other way is to have them both accessible and to make sure you lock the mutex before you use aPass.
pthread_mutex_lock(aPass_lock);
do something with aPass
pthread_mutex_unlock(aPass_lock);
But what if someone new comes on the project, what if you forget one time to lock it. I don't like debugging thread problems they are hard.
Is there a good way to (using pthreads because i have to use QNX which has little boost support) To lock single variables without needing a big class and that is safer then just creating a mutex lock to go with it?

std::atomic<double> aPass;
provided you have C++11.

To elabourate on my solution, it would be something like this.
template <typename ThreadSafeDataType>
class ThreadSafeData{
//....
private:
ThreadSafeDataType data;
mutex mut;
};
class apass:public ThreadSafeData<int>
Additionally, to make it unique, it might be best to make all operators and members static. For this to work you need to use CRTP
i.e
template <typename ThreadSafeDataType,class DerivedDataClass>
class ThreadSafeData{
//....
};
class apass:public ThreadSafeData<int,apass>

You can easily make your own class that locks the mutex on construction, and unlocks it on destruction. This way, no matter what happens the mutex will be freed on return, even if an exception is thrown, or any path is taken.
class MutexGuard
{
MutexType & m_Mutex;
public:
inline MutexGuard(MutexType & mutex)
: m_Mutex(mutex)
{
m_Mutex.lock();
};
inline ~MutexGuard()
{
m_Mutex.unlock();
};
}
class TestClass
{
MutexType m_Mutex;
double m_SharedVar;
public:
TestClass()
: m_SharedVar(4.0)
{ }
static void Function1()
{
MutexGuard scopedLock(m_Mutex); //lock the mutex
m_SharedVar+= 2345;
//mutex automatically unlocked
}
static void Function2()
{
MutexGuard scopedLock(m_Mutex); //lock the mutex
m_SharedVar*= 234;
throw std::runtime_error("Mutex automatically unlocked");
}
}
The variable m_SharedVar is ensured mutual exclusion between Function1() and Function2() , and will always be unlocked on return.
boost has build in types to accomplish this: boost::scoped_locked, boost::lock_guard.

You can create a class which act as a generic wrapper around your variable synchronising the access to it.
Add operator overloading for the assignment and you are done.

Consider use RAII idiom, below code is just the idea, it's not tested:
template<typename T, typename U>
struct APassHelper : boost::noncoypable
{
APassHelper(T&v) : v_(v) {
pthread_mutex_lock(mutex_);
}
~APassHelper() {
pthread_mutex_unlock(mutex_);
}
UpdateAPass(T t){
v_ = t;
}
private:
T& v_;
U& mutex_;
};
double aPass;
int baPass_lock;
APassHelper<aPass,aPass_lock) temp;
temp.UpdateAPass(10);

You can modify your aPass class by using operators instead of get/set:
class aPass {
public:
aPass() {
pthread_mutex_init(&aPass_lock, NULL);
aPass_ = 0;
}
operator double () const {
double setMe;
pthread_mutex_lock(aPass_lock);
setMe = aPass_;
pthread_mutex_unlock(aPass_lock);
return setMe;
}
aPass& operator = (double setThis) {
pthread_mutex_lock(aPass_lock);
aPass_ = setThis;
pthread_mutex_unlock(aPass_lock);
return *this;
}
private:
double aPass_;
pthread_mutex_t aPass_lock;
};
Usage:
aPass a;
a = 0.5;
double b = a;
This could of course be templated to support other types. Note however that a mutex is overkill in this case. Generally, memory barriers are enough when protecting loads and stores of small data-types. If possible you should use C++11 std::atomic<double>.

Related

std::unique_ptr with RAII for mutex?

We have a lot of legacy C++98 code that we are slowly upgrading to c++11 and we have a RAII implementation for custom Mutex class:
class RaiiMutex
{
public:
RaiiMutex() = delete;
RaiiMutex(const RaiiMutex&) = delete;
RaiiMutex& operator= (const RaiiMutex&) = delete;
RaiiMutex(Mutex& mutex) : mMutex(mutex)
{
mMutex.Lock();
}
~RaiiMutex()
{
mMutex.Unlock();
}
private:
Mutex& mMutex;
};
Is it ok to make an std::unique_ptr of this object? We would still benefit from automatically calling the destructor when the object dies (thus unlocking) and would also gain the ability of unlocking before non-critical operations.
Example legacy code:
RaiiMutex raiiMutex(mutex);
if (!condition)
{
loggingfunction();
return false;
}
After:
auto raiiMutex = std::unique_ptr<RaiiMutex>(new RaiiMutex(mutex));
if (!condition)
{
raiiMutex = nullptr;
loggingfunction(); // log without locking the mutex
return false;
}
It would also remove the use of unnecessary brackets:
Example legacy code:
Data data;
{
RaiiMutex raiiMutex(mutex);
data = mQueue.front();
mQueue.pop_front();
}
data.foo();
After:
auto raiiMutex = std::unique_ptr<RaiiMutex>(new RaiiMutex(mutex));
Data data = mQueue.front();
mQueue.pop_front();
raiiMutex = nullptr;
data.foo();
Does it make sense?
Edit:
Cannot use unique_lock due to custom Mutex class:
class Mutex
{
public:
Mutex();
virtual ~Mutex();
void Unlock(bool yield = false);
void Lock();
bool TryLock();
bool TimedLock(uint64 pWaitIntervalUs);
private:
sem_t mMutex;
};
Add Mutex::lock(), Mutex::unlock() and Mutex::try_lock() methods to Mutex. They just forward to the Lock etc methods.
Then use std::unique_lock<Mutex>.
If you cannot modify Mutex, wrap it.
struct SaneMutex: Mutex {
void lock() { Lock(); }
// etc
using Mutex::Mutex;
};
A SaneMutex replaces a Mutex everywhere you can.
Where you can't:
struct MutexRef {
void lock() { m.Lock(); }
// etc
MutexRef( Mutex& m_in ):m(m_in) {}
private:
Mutex& m;
};
include an adapter.
these match the C++ standard lockable requirements. If you want timed lockable, you have to write a bit of glue code.
auto l = std::unique_lock<MutexRef>( mref );
or
auto l = std::unique_lock<SaneMutex>( m );
you now have std::lock, std::unique_lock, std::scoped_lock support.
And your code is one step closer to using std::mutex.
As for your unique_ptr solution, I wouldn't add the overhead of a memory allocation on every time you lock a mutex casually.

Make accesible my stack from other threads c++

I have a list of thread like this;
Kitchen::Kitchen(double multiplier, size_t cooks, size_t restock) :
_multiplier(multiplier), _ncooks(cooks), _restock(restock)
{
Cook *cook;
std::stack<APizza *> orders;
this->_ingredients = new Stock();
this->_ordersNow = 0;
this->_socket = initControlSocket();
for (size_t i = 0; i != _ncooks; i++) {
cook = new Cook(this, this->_multiplier);
this->_cooks.push_back(std::thread(&Cook::Run, cook));
}
dprintf(this->_socket, "%d\r\n", KITCHEN_OPENED);
}
i Want to make the std::stack< APizza *> orders; accessible and usable by all my threads in this->_cooks
Note that your threads may need a way to synchronize access to the stack, using a mutex for example, so you need to pass a reference to a mutex as well.
Have Cook::Run accept these arguments by reference:
void Run(std::mutex &, std::stack<APizza *> &);
Then pass a reference to them when you create the thread:
this->_cooks.push_back(std::thread(
&Cook::Run, cook,
std::ref(orders_mutex),
std::ref(orders)
));
As mentioned by others in the comment section, the stack will be destroyed when control leaves the Kitchen constructor. To prevent this, you could make the stack a data member of Kitchen.
Alternatively, since you need a mutex on this stack to synchronize concurrent access, you could create a wrapper class that holds the stack and the mutex, and guards access to the stack using the mutex.
template <typename T>
class threadsafe_stack {
public:
void push(T value) {
std::unique_lock<std::mutex> lock{mutex};
stack.push(std::move(value));
}
std::optional<T> pop() {
std::unique_lock<std::mutex> lock{mutex};
if (!stack.empty()) {
T val{std::move(stack.top())};
stack.pop();
return val;
}
return {};
}
private:
std::stack<T> stack;
std::mutex mutex;
};

Is there a `shared_lock_guard` and if not, what would it look like?

I wanted to use a std::mutex in my class, and noticed that it isn't copyable. I'm at the bottom level of my library here, so it seems like a terrible idea to have this behaviour.
I used std::lock_guard on the std::mutex, but there doesn't seem to be a shared_lock_guard, which would be preferable to provide write-locks-exclusively behaviour. Is this an oversight or trivial to implement myself?
With C++14 You can use a std::shared_lock and a std::unique_lock to implement read/write locking:
class lockable
{
public:
using mutex_type = std::shared_timed_mutex;
using read_lock = std::shared_lock<mutex_type>;
using write_lock = std::unique_lock<mutex_type>;
private:
mutable mutex_type mtx;
int data = 0;
public:
// returns a scoped lock that allows multiple
// readers but excludes writers
read_lock lock_for_reading() { return read_lock(mtx); }
// returns a scoped lock that allows only
// one writer and no one else
write_lock lock_for_writing() { return write_lock(mtx); }
int read_data() const { return data; }
void write_data(int data) { this->data = data; }
};
int main()
{
lockable obj;
{
// reading here
auto lock = obj.lock_for_reading(); // scoped lock
std::cout << obj.read_data() << '\n';
}
{
// writing here
auto lock = obj.lock_for_writing(); // scoped lock
obj.write_data(7);
}
}
Note: If you have C++17, then you can use std::shared_mutex for mutex_type.
It’s not part of C++ standard yet, but you can find implementation example in boost.
template<typename SharedMutex>
class shared_lock_guard
{
private:
SharedMutex& m;
public:
typedef SharedMutex mutex_type;
explicit shared_lock_guard(SharedMutex& m_):
m(m_)
{
m.lock_shared();
}
shared_lock_guard(SharedMutex& m_,adopt_lock_t):
m(m_)
{}
~shared_lock_guard()
{
m.unlock_shared();
}
};
It requires mutex class conforming to SharedMutex concept though;
std::shared_mutex is part of proposed C++17 standard and boost had one already for some time: boost::shared_mutex.

Scoped mutex lock

I never really worked with mutexes before, but i need to control access to protected resources. Looking through the new C++11 stuff, i cooked up this class:
class CMutex
{
public:
class Lockable
{
friend class CMutex;
std::atomic_flag flag;
public:
Lockable()
{
flag.clear();
}
};
private:
Lockable * resource;
CMutex(const CMutex &);
public:
CMutex(Lockable * l)
{
resource = l;
acquire(l);
}
CMutex(Lockable & l)
{
resource = &l;
acquire(l);
}
CMutex()
: resource(nullptr)
{
}
~CMutex()
{
if (resource)
release(resource);
}
void acquire(Lockable * l)
{
if (!resource)
resource = l;
if (!spinLock(2000, resource))
//explode here
return;
}
void acquire(Lockable & l)
{
acquire(&l);
}
private:
void release(Lockable * l)
{
if (l)
l->flag.clear();
}
static bool spinLock(int ms, Lockable * bVal)
{
using namespace Misc;
long start;
int ret;
loop:
start = QuickTime();
while (bVal->flag.test_and_set()) {
if ((QuickTime() - start) > ms)
goto time_out;
// yield thread
Delay(0);
}
// normal exitpoint
return true;
// deadlock occurs
time_out:
// handle error ...
}
}
Usage like so:
class MyClass : public CMutex::lockable
{
...
void doStuff()
{
// lock data
CMutex(this);
// do stuff
...
// mutex should automagically be RAII released here
}
...
};
First of all, I'm interested in whether this concept actually works how it should (given the implementation of std::atomic etc.)?
Secondly, I noticed that it correctly obtains the lock, however it releases it instantly. I guess i should give the lock a name?
CMutex lock(this);
However, isn't the compiler free to destruct the object before the scope is left as an optimization provided it can guarantee that i wont interact more with the object? This would defeat the purpose of this construct, if i can't guarantee that the destructor only will be called at scope exit.
Regards
No, the compiler is not free to destruct before the scope ends.
Per the C++ Standard section 12.4/10
— for constructed objects with automatic storage duration (3.7.3) when the block in which an object is created exit.
Here is a trick that may come handy for you and it works with all mainstream (VC++, clang, gcc) compilers:
#define APPEND_ID1(id1, id2) id1##id2
#define APPEND_ID2(id1, id2) APPEND_ID1(id1, id2)
#define APPEND_COUNTER(id) APPEND_ID2(id, __COUNTER__)
#define SCOPED_LOCK(lockable) CMutex APPEND_COUNTER(scoped_lock)(lockable)
class MyClass : public CMutex::lockable
{
...
void doStuff()
{
// lock data
SCOPED_LOCK(this);
// auto-generates a unique name, works even with multiple locks in the same scope..
SCOPED_LOCK(that);
// do stuff
...
// mutex should automagically be RAII released here
}

How to safely destroy an object, that is frequently accessed by two different threads?

I currently ran into the Problem that an Object (Instance), that is frequently accessed by two different threads, has to be freed. For me it does not really matter which of the two threads is destructing the instance but i would prefer the one, that also creates it, although i think this does not matter at all.
So in a scenario where the thread that is supposed to destroy the object, detects that it should be deleted, and while calling the destructor, the other thread is accessing a member (function) of that object, probably some sort of runtime error will occur.
I did some research on this topic, but i could just figure out people saying: "Why deleting an Object that is still needed to exist". But in my case it should stop being needed after the piece of code that one thread is executing decides to destroy it.
I would appreciate an answer, like a hint to a nice book or article which covers this topic, but feel free to write how you would solve this problem.
You would need a double indirection, to manage concurrent access to the data:
class Object {
public;
class Data {
int get_value() const;
void set_value(int);
};
class Guard {
public:
Guard(Nutex& mutex, Data* data)
: data(data)
{
if( ! data) throw std::runtime_error("No Data");
mutex.lock();
}
~Guard()
{
mutex.unlock();
}
Data& data() { return *m_data; }
private:
Data* data;
};
class ConstGuard {
public:
ConstGuard(Mutex& mutex, const Data* data)
: data(data)
{
if( ! data) throw std::runtime_error("No Data");
mutex.lock();
}
~ConstGuard()
{
mutex.unlock();
}
const Data& data() const { return *m_data; }
private:
const Data* data;
};
private:
friend std::shared_ptr<Object> make_object(const Data&);
Object(const Data& data)
: data(new Data(data))
{}
public:
~Object()
{
delete data;
}
/// Self destruction.
void dispose() {
Guard guard(get());
delete data;
data = 0;
}
// For multiple operations use a Guard.
Guard get() { return Guard(mutex, data); }
ConstGuard get() const { return ConstGuard(mutex, data); }
// For single operations you may provide convenience functions.
int get_value() const { return ConstGuard(mutex, data).data().get_value(); }
void set_value(int value) { Guard(mutex, data).data().set_value(value); }
private:
mutable Mutex mutex;
data* data;
};
std::shared_ptr<Object> make_object(const Object::Data& data) {
return std::make_shared<Object>(data);
}
(Note: The above code is just a sketch, I have not compiled it)
That was the long story. The short one is [20.7.2.5] shared_ptr atomic access:
Concurrent access to a shared_ptr object from multiple threads does not
introduce a data race if the access is done exclusively via the functions
in this section and the instance is passed as their first argument.
shared_ptr atomic_load(const shared_ptr* p);
void atomic_store(shared_ptr* p, shared_ptr r);
...
But I am not familiar with these functions.
The thread which should not destroy the object should hold it using a std::weak_ptr, except for the times when it is actively using it. During these times, the weak_ptr can be upgraded to a std::shared_ptr.
The thread which should destroy it now can hold on to its shared_ptr for as long as it thinks appropriate, and discard that shared_ptr afterwards. If the other thread only has a weak_ptr (not actively using it), the object will go away. if the other thread also has a shared_ptr, it holds on to the object until the operation finishes.