Const cast to allow read lock, is this smell bad?

I want to execute a read-only method for an object marked as const , but in order to make it thread-safe, I need to lock the mutex-reader-writer:

 const Value Object::list() const { ScopedRead lock(children_); ... } 

But this breaks down because the compiler complains about "children_" being const and the like. I went up to the ScopedRead class and before the RWMutex class (which children_ is a subclass of) to enable read_lock for the const object, but I have to write this:

 inline void read_lock() const { pthread_rwlock_rdlock(const_cast<pthread_rwlock_t*>(&rwlock_)); } 

I always found out that const_cast is the smell of code. Any way to avoid this?

+6
c ++ concurrency const
source share
5 answers

Make lock mutable

 mutable pthread_rwlock_t rwlock; 

This is a common scenario in which mutable is used. Requesting a read-only object (as the name implies) means an operation that does not require non-constant access. Mutable is considered good practice when you want to be able to change parts of an object that are not visible or have observable side effects for the object. Your lock is used to provide sequential access to the data of the object, and changing it does not affect the data contained in the object, and has no observed side effects for subsequent calls, so it still respects the constant of the object.

+13
source share

Make the mutable lock.

+6
source share

Yes, use mutable. It is intended for this purpose: where is the entire context of the const function (i.e., an Accessor or some other action that is logically readable.), But where some element of write access is needed for the mutex or reference counter, etc. .

The function must be const, even if it blocks the mutex within itself. This makes the code neutral, without having to reveal the details that I believe is what you are trying to do.

There are very few places where const_cast<> should be legally used, and this is not one of them. Using const on an object, especially in a const function, is a nightmare for serving code. Consider:

 token = strtok_r( const_cast<char*>( ref_.c_str() ), ":", &saveptr ); 

Actually, I would say that when you see const_cast in a const function, you should start by saying that the function is not const (very soon after you have to get rid of const_cast and execute the const function again) / p>

0
source share

Well, if we are not allowed to modify the variable declaration, then const_cast comes to the rescue. If not, then making this changeable is the solution.

0
source share

To solve the real problem, declare the lock as mutable.

Now my professional opinion is as follows:

The compiler is right to complain, and you're right to find it mildly offensive. If a read-only operation requires a lock, and locks must be written to lock, then you should probably make a read request that requires non-constant access.

EDIT: Alright, I will bite. I saw how this type of template triggers major hits in places you did not expect. Does anyone know how a tolower or toupper can become a major bottleneck if called often enough, even from the default ASCII locale? In one specific implementation of the C runtime library created for multithreading, a lock was taken to query the current locale for this thread. Calling a tolower order of 10,000 times or more led to more tricks than reading a file from disk.

Just because you want read-only access does not mean that you should hide the fact that you need to block it.

-3
source share

All Articles