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.
Related
I'm reading Functional Programming in C++ from Ivan Čukić, and I am having a hard time interpreting a point in the summary of Chapter 5:
When you make a member function const, you promise that the function won't change any data in the class (not a bit of the object will change), or that any changes to the object (to members declared as mutable) will be atomic as far as the users of the object are concerned.
If the part in italic was simply are limited to members declared as mutable I would have been happy with it. However, this rewording of mine seems to correspond to what the author put in parenthesis. What is out of parenthesis is what is puzzling me: what is the meaning of atomic in that sentence?
The author is making a claim about best practices, not about the rules of the language.
You can write a class in which const methods alter mutable members in ways that are visible to the user, like this:
struct S {
mutable int value = 0;
int get() const {
return value++;
}
};
const S s;
std::cout << s.get(); // prints 0
std::cout << s.get(); // prints 1
// etc
You can do that, and it wouldn't break any of the rules of the language. However, you shouldn't. It violates the user's expectation that the const method should not change the internal state in an observable way.
There are legitimate uses for mutable members, such as memoization that can speed up subsequent executions of a const member function.
The author suggests that, as a matter of best practices, such uses of mutable members by const member functions should be atomic, since users are likely to expect that two different threads can call const member functions on an object concurrently.
If you violate this guideline, then you're not directly breaking any rules of the language. However, it makes it likely that users will use your class in a way that will cause data races (which are undefined behaviour). It takes away the user's ability to use the const qualifier to reason about the thread-safety of your class.
or that any changes to the object (to members declared as mutable)
will be atomic as far as the users of the object are concerned.
I think the author (or editor) of the book worded his statement poorly there -- const and mutable make no guarantees about thread-safety; indeed, they were part of the language back when the language had no support for multithreading (i.e. back when multithreading specifications were not part of the C++ standard and therefore anything you did with multithreading in your C++ program was therefore technically undefined behavior).
I think what the author intended to convey is that changes to mutable member-variables from with a const-tagged method should be limited only to changes that don't change the object's state as far as the calling code can tell. The classic example of this would be memo-ization of an expensive computation for future reference, e.g.:
class ExpensiveResultGenerator
{
public:
ExpensiveResultGenerator()
: _cachedInputValue(-1)
{
}
float CalculateResult(int inputValue) const
{
if ((_cachedInputValue < 0)||(_cachedInputValue != inputValue))
{
_cachedInputValue = inputValue;
_cachedResult = ReallyCPUExpensiveCalculation(inputValue);
}
return _cachedResult;
}
private:
float ReallyCPUExpensiveCalculation(int inputValue) const
{
// Code that is really expensive to calculate the value
// corresponding to (inputValue) goes here....
[...]
return computedResult;
}
mutable int _cachedInputValue;
mutable float _cachedResult;
}
Note that as far as the code using the ExpensiveResultGenerator class is concerned, CalculateResult(int) const doesn't change the state of the ExpensiveResultGenerator object; it is simply computing a mathematical function and returning the result. But internally we are making a memo-ization optimization so that if the user calls CalculateResult(x) with the same value for x multiple times in a row, we can skip the expensive calculation after the first time and just return the _cachedResult instead, for a speedup.
Of course, making that memo-ization optimization can introduce race conditions in a multi-threaded environment, since now we are changing state variables even if the calling code can't see us doing it. So to do this safely in a multithreaded environment, you would need to employ a Mutex of some sort to serialize accesses to the two mutable variables -- either that, or require the calling code to serialize any calls to CalculateResult().
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;
}
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.)
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).
I have a class member myMember that is a myType pointer. I want to assign this member in a function that is declared as const. I'm doing as follows:
void func() const
{
...
const_cast<myType*>(myMember) = new myType();
...
}
Doing this works fine in VC++, but GCC gives an error with the message "lvalue required as left operand of assignment".
Making the member mutable allow me to simply remove the const_cast and assign the value. However, I'm not entirely sure that that comes with other side-effects.
Can I assign my member without having to make the member mutable? How? Are there any side-effects in making members mutable?
This scenario -- an encapsulated internal state change that does not impact external state (e.g. caching results) -- is exactly what the mutable keyword is for.
The code wont actually work in VC++ - you're not updating the value (or at least it shouldnt), hence the warning from GCC. Correct code is
const_cast<myType*&>(myMember) = new myType();
or [from other response, thanks :P]:
const_cast<ThisType*>(this)->myMember = new myType();
Making it mutable effectively means you get implicit const_casts in const member functions, which is generally what you should be steering towards when you find yourself doing loads of const_casts on this. There are no 'side-effects to using mutable' other than that.
As you can see from the vehement debates circling this question, willy-nilly usage of mutable and lots of const_casts can definitely be symptoms of bad smells in your code. From a conceptual point of view, casting away constness or using mutable can have much larger implications. In some cases, the correct thing to do may be to change the method to non-const, i.e., own up to the fact that it is modifying state.
It all depends on how much const-correctness matters in your context - you dont want to end up just sprinking mutable around like pixie dust to make stuff work, but mutable is intended for usage if the member isnt part of the observable state of the object. The most stringent view of const-correctness would hold that not a single bit of the object's state can be modified (e.g., this might be critical if you're instance is in ROM...) - in those cases you dont want any constness to be lost. In other cases, you might have some external state stored somewhere ouside of the object - e.g., a thread-specific cache which also needs to be considered when deciding if it is appropriate.
const_cast is nearly always a sign of design failure. In your example, either func() should not be const, or myMember should be mutable.
A caller of func() will expect her object not to change; but this means "not to change in a way she can notice"; this is, not to change its external state. If changing myMember does not change the object external state, that is what the mutable keyword is for; otherwise, func() should not be const, because you would be betraying your function guarantees.
Remember that mutable is not a mechanism to circunvent const-correctness; it is a mechanism to improve it.
class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};
As Steve Gilham wrote, mutable is the correct (and short) answer to your question. I just want to give you a hint in a different direction.
Maybe it's possible in your szenario to make use of an (or more than one) interface?
Perhaps you can grok it from the following example:
class IRestrictedWriter // may change only some members
{
public:
virtual void func() = 0;
}
class MyClass : virtual public IRestrictedWriter
{
public:
virtual void func()
{
mValueToBeWrittenFromEverybody = 123;
}
void otherFunctionNotAccessibleViaIRestrictedWriter()
{
mOtherValue1 = 123;
mOtherValue2 = 345;
}
...
}
So, if you pass to some function an IRestrictedReader * instead of a const MyClass * it can call func and thus change mValueToBeWrittenFromEverybody whereas mOtherValue1 is kind of "const".
. I find mutable always a bit of a hack (but use it sometimes).