Protecting C++ classes with pthreads and references - c++

If I have a private member of a class which may be modified by a background thread, and a getter for said private member, can I use a const reference to that private member for the getter or must I protect the getter with a mutex to ensure safety? Here is some example code. Note that I am not using C++11 so I do not have access to those features. I am aware of std::atomic and std::lock_guard and their uses but the code I am working on at this moment uses C++03.
It is worth noting that shared_member's type int is more of a placeholder for simplicity
If there is a nicer way to ensure safety than the get_copyof_shared_int() method, I am all ears. However if the reference will be safe that will also work, I only want to ensure safety.
#include <pthread.h>
using namespace std;
class testclass{
public:
// return reference to shared_member (provided only as example of ideal getter)
inline const int& get_shared_member () const{
return shared_member;
}
// return copy of shared_member (example of getter known to be thread safe )
inline const int get_copyof_shared_int () {
pthread_mutex_lock(&shared_int_mutex);
int shared_member_copy = shared_member;
pthread_mutex_unlock(&shared_int_mutex);
return shared_member_copy;
}
// initializes shared_member and mutex, starts running background_thread
void init(int);
private:
volatile int shared_member; //should be marked volatile because it is used in background_thread()
pthread_mutex_t shared_int_mutex;
// thread which may modify shared_member
static void *background_thread(void *arg);
};

Unfortunately yes, technically you should protect the getter since int operations are not guaranteed to be atomic.
As for the getter, it looks about as simple as it gets, although I'm not sure why you have two different getters.
EDIT: Don't forget to mark your shared variable as volatile as pointed out in the link above. Otherwise the optimizing compiler may make some improper optimizations since it can assume (wrongly in your case) the variable won't be set by another thread.

Taking a reference to it is essentially like passing a pointer (references are usually implemented as a contractual layer over pointers).
That means there is no guarantee that your thread won't read the value at some inconvenient time such as when the other thread, on a different core, is in the middle of writing to it.
Also, you might want to look into C++1's and headers.
I would also advise against inlining a getter with a mutex.
const int get_copyof_shared_int () {
std::lock_guard<std::mutex> lock(shared_int_mutex);
return shared_int;
}

Related

Is there anything that would make a static bool thread safe?

I recently came across some code that was working fine where a static bool was shared between multiple threads (single writer, multiple receivers) although there was no synchronization.
Something like that (simplified):
//header A
struct A {
static bool f;
static bool isF() { return f; }
};
//Source A
bool A::f = false;
void threadWriter(){
/* Do something */
A::f = true;
}
// Source B
void threadReader(){
while (!A::isF()) { /* Do something */}
}
For me, this kind of code has a race condition in that even though operations on bool are atomic (on most CPUs), we have no guarantee that the write from the writer thread will be visible to the reader threads. But some people told me that the fact that f is static would help.
So, is there anything in C++11 that would make this code safe? Or anything related to static that would make this code work?
Your hardware may be able to atomically operate on a bool. However, that does not make this code safe. As far as C++ is concerned, you are writing and reading the bool in different threads without synchronisation, which is undefined.
Making the bool static does not change that.
To access the bool in a thread-safe way you can use a std::atomic<bool>. Whether the atomic uses a mutex or other locking is up to the implementation.
Though, also a std::atomic<bool> is not sufficient to synchronize the threadReader() and threadWriter() in case each /*Do something */ is accessing the same shared data.
But some people told me that the fact that f is static would help.
Frankly, this sounds like cargo-cult. I can imagine that this was confused with the fact that initialization of static local variables is thread safe. From cppreference:
If multiple threads attempt to initialize the same static local
variable concurrently, the initialization occurs exactly once (similar
behavior can be obtained for arbitrary functions with std::call_once).
Note: usual implementations of this feature use variants of the
double-checked locking pattern, which reduces runtime overhead for
already-initialized local statics to a single non-atomic boolean
comparison.
Look for Meyers singleton to see an example of that. Though, this is merely about initialization. For example here:
int& foo() {
static int x = 42;
return x;
}
Two threads can call this function concurrently and x will be initialized exactly once. This has no impact on thread-safety of x itself. If two threads call foo and one writes and another reads x there is a data race. However, this is about initialization of static local variables and has nothing to do with your example. I don't know what they meant when they told you static would "help".

Thread safety of const reference return of const method

Consider this class:
#include <vector>
class A {
private:
std::vector<int> m_vector;
public:
void insertElement(int i) {
m_vector.push_back(i);
}
const std::vector<int>& getVectorRef() const {
return m_vector;
}
};
Is the method getVectorRef thread safe?
Is it possible that during the return of getVectorRef another thread pops in and calls insertElementsuch that the member vector gets changed and the caller of getVectorRef gets a wrong const reference?
Have the two const qualifiers(one for the vector and the other for the method) no meaning in the context of thread safety?
The member function is thread safe, your interface isn't. In a class that is designed to be thread safe, you cannot yield references to the objects that you maintain, as if the user keeps the reference laying around she can use it while other operation is in place.
The member function is technically thread safe. The reference to the member is basically it's address, and that address cannot change. Whatever the other threads are doing, the reference will always refer to exactly the same object. But that is usually not your main concern. The real concern is what can the user do with the return of the function, and in this case the answer is basically nothing.
As soon as the user gets the reference, any access through it is going to cause a race condition when combined with any modification of that member in the original object. You cannot provide safe synchronization once you give references away, there is no way to make a thread safe interface out of a class that yields references.
If you need to make access thread safe, you can opt to either copy the value (within a critical section) or provide more fine grained functions that will handle the higher level requests from the user.
I'd recommend C++ concurrency in action by Anthony Williams for some of the discussions on how to make an interface thread safe.

Should I use const to make objects thread-safe?

I wrote a class which instances may be accessed by several threads. I used a trick to remember users they have to lock the object before using it. It involves keeping only const instances. When in the need to read or modify sensitive data, other classes should call a method (which is const, thus allowed) to get a non-const version of the locked object. Actually it returns a proxy object containing a pointer to the non-const object and a scoped_lock, so it unlocks the object when going out of scope. The proxy object also overloads operator-> so the access to the object is transparent.
This way, shooting onself's foot by accessing unlocked objects is harder (there is always const_cast).
"Clever tricks" should be avoided, and this smells bad anyway.
Is this design really bad ?
What else can I or should I do ?
Edit: Getters are non-const to enforce locking.
Basic problem: a non-const reference may exist elsewhere. If that gets written safely, it does not follow that it can be read safely -- you may look at an intermediate state.
Also, some const methods might (legitimately) modify hidden internal details in a thread-unsafe way.
Analyse what you're actually doing to the object and find an appropriate synchronisation mode.
If your clever container really does know enough about the objects to control all their synchronisation via proxies, then make those objects private inner classes.
This is clever, but unfortunately doomed to fail.
The problem, underlined by spraff, is that you protect against reads but not against writes.
Consider the following sequence:
unsigned getAverageSalary(Employee const& e) {
return e.paid() / e.hired_duration();
}
What happens if we increment paid between the two function calls ? We get an incoherent value.
The problem is that your scheme does not explicitly enforce locking for reads.
Consider the alternative of a Proxy pattern: The object itself is a bundle of data, all privates. Only a Proxy class (friend) can read/write its data, and when initializing the Proxy it grabs the lock (on the mutex of the object) automatically.
class Data {
friend class Proxy;
Mutex _mutex;
int _bar;
};
class Proxy {
public:
Proxy(Data& data): _lock(data._mutex), _data(data) {}
int bar() const { return _data._bar; }
void bar(int b) { _data._bar = b; }
private:
Proxy(Proxy const&) = delete; // disable copy
Lock _lock;
Data& _data;
};
If I wanted to do what you are doing, I would do one of the following.
Method 1:
shared_mutex m; // somewhere outside the class
class A
{
private:
int variable;
public:
void lock() { m.lock(); }
void unlock() { m.unlock(); }
bool is_locked() { return m.is_locked(); }
bool write_to_var(int newvalue)
{
if (!is_locked())
return false;
variable = newvalue;
return true;
}
bool read_from_var(int *value)
{
if (!is_locked() || value == NULL)
return false;
*value = variable;
return true;
}
};
Method 2:
shared_mutex m; // somewhere outside the class
class A
{
private:
int variable;
public:
void write_to_var(int newvalue)
{
m.lock();
variable = newvalue;
m.unlock();
}
int read_from_var()
{
m.lock();
int to_return = variable;
m.unlock();
return to_return;
}
};
The first method is more efficient (not locking-unlocking all the time), however, the program may need to keep checking the output of every read and write to see if they were successful. The second method automatically handles the locking and so the programmer wouldn't even know the lock is there.
Note: This is not code for copy-paste. It shows a concept and sketches how it's done. Please don't comment saying you forgot some error checking somewhere.
This sounds a lot like Alexandrescu's idea with volatile. You're not
using the actual semantics of const, but rather exploiting the way the
type system uses it. In this regard, I would prefer Alexandrescu's use
of volatile: const has very definite and well understood semantics,
and subverting them will definitely cause confusion for anyone reading
or maintaining the code. volatile is more appropriate, as it has no
well defined semantics, and in the context of most applications, is not
used for anything else.
And rather than returning a classical proxy object, you should return a
smart pointer. You could actually use shared_ptr for this, grabbing
the lock before returning the value, and releasing it in the deleter
(rather than deleting the object); I rather fear, however, that this
would cause some confusion amongst the readers, and I would probably go
with a custom smart pointer (probably using shared_ptr with the custom
deleter in the implementation). (From your description, I suspect that
this is closer to what you had in mind anyway.)

Should mutexes be mutable?

Not sure if this is a style question, or something that has a hard rule...
If I want to keep the public method interface as const as possible, but make the object thread safe, should I use mutable mutexes? In general, is this good style, or should a non-const method interface be preferred? Please justify your view.
The hidden question is: where do you put the mutex protecting your class?
As a summary, let's say you want to read the content of an object which is protected by a mutex.
The "read" method should be semantically "const" because it does not change the object itself. But to read the value, you need to lock a mutex, extract the value, and then unlock the mutex, meaning the mutex itself must be modified, meaning the mutex itself can't be "const".
If the mutex is external
Then everything's ok. The object can be "const", and the mutex don't need to be:
Mutex mutex ;
int foo(const Object & object)
{
Lock<Mutex> lock(mutex) ;
return object.read() ;
}
IMHO, this is a bad solution, because anyone could reuse the mutex to protect something else. Including you. In fact, you will betray yourself because, if your code is complex enough, you'll just be confused about what this or that mutex is exactly protecting.
I know: I was victim of that problem.
If the mutex is internal
For encapsulation purposes, you should put the mutex as near as possible from the object it's protecting.
Usually, you'll write a class with a mutex inside. But sooner or later, you'll need to protect some complex STL structure, or whatever thing written by another without mutex inside (which is a good thing).
A good way to do this is to derive the original object with an inheriting template adding the mutex feature:
template <typename T>
class Mutexed : public T
{
public :
Mutexed() : T() {}
// etc.
void lock() { this->m_mutex.lock() ; }
void unlock() { this->m_mutex.unlock() ; } ;
private :
Mutex m_mutex ;
}
This way, you can write:
int foo(const Mutexed<Object> & object)
{
Lock<Mutexed<Object> > lock(object) ;
return object.read() ;
}
The problem is that it won't work because object is const, and the lock object is calling the non-const lock and unlock methods.
The Dilemma
If you believe const is limited to bitwise const objects, then you're screwed, and must go back to the "external mutex solution".
The solution is to admit const is more a semantic qualifier (as is volatile when used as a method qualifier of classes). You are hiding the fact the class is not fully const but still make sure provide an implementation that keeps the promise that the meaningful parts of the class won't be changed when calling a const method.
You must then declare your mutex mutable, and the lock/unlock methods const:
template <typename T>
class Mutexed : public T
{
public :
Mutexed() : T() {}
// etc.
void lock() const { this->m_mutex.lock() ; }
void unlock() const { this->m_mutex.unlock() ; } ;
private :
mutable Mutex m_mutex ;
}
The internal mutex solution is a good one IMHO: Having to objects declared one near the other in one hand, and having them both aggregated in a wrapper in the other hand, is the same thing in the end.
But the aggregation has the following pros:
It's more natural (you lock the object before accessing it)
One object, one mutex. As the code style forces you to follow this pattern, it decreases deadlock risks because one mutex will protect one object only (and not multiple objects you won't really remember), and one object will be protected by one mutex only (and not by multiple mutex that needs to be locked in the right order)
The mutexed class above can be used for any class
So, keep your mutex as near as possible to the mutexed object (e.g. using the Mutexed construct above), and go for the mutable qualifier for the mutex.
Edit 2013-01-04
Apparently, Herb Sutter have the same viewpoint: His presentation about the "new" meanings of const and mutable in C++11 is very enlightening:
http://herbsutter.com/2013/01/01/video-you-dont-know-const-and-mutable/
[Answer edited]
Basically using const methods with mutable mutexes is a good idea (don't return references by the way, make sure to return by value), at least to indicate they do not modify the object. Mutexes should not be const, it would be a shameless lie to define lock/unlock methods as const...
Actually this (and memoization) are the only fair uses I see of the mutable keyword.
You could also use a mutex which is external to your object: arrange for all your methods to be reentrant, and have the user manage the lock herself : { lock locker(the_mutex); obj.foo(); } is not that hard to type, and
{
lock locker(the_mutex);
obj.foo();
obj.bar(42);
...
}
has the advantage it doesn't require two mutex locks (and you are guaranteed the state of the object did not change).

C++ mutex and const correctness

Is there convention regarding whenever method which is essentially read-only, but has mutex/ lock which may need to be modified, is const or not?
if there is not one, what would be disadvantage/bad design if such method is const
Thank you
You can mark data members with the keyword mutable to allow them to be modified in a constant member function, e.g.:
struct foo
{
mutable mutex foo_mutex;
// ....
void bar() const
{
auto_locker lock(foo_mutex);
// ...
}
};
Try to do this as little as possible because abusing mutable is evil.
I'm generally OK with mutable locks and caches for methods that are conceptually const.
Especially in the case of caching the result of a calculation for performance. That's strictly an implementation detail that shouldn't be of concern to the callers, so removing the const designation would be tantamount to a small leak in the abstraction.
With locks, I'd ask myself if the lock is just a private implementation detail. If the lock is shared with other objects, then it's actually part of the interface.
On some platforms, locks are accessed through handles, so you can use const on the method without worrying about mutable.