
Howard Hinnant wrote:
On Jul 11, 2004, at 8:46 AM, Peter Dimov wrote:
[...]
Mutex * mutex() const; // returns: the associated mutex;
Why return a pointer instead of a reference? What about this instead?
Mutex& mutex(); const Mutex& mutex() const;
Because of the use case shown below:
void f( scoped_lock & lock ) { // check for lock validity assert( lock.locked() && lock.mutex() == &my_mutex );
// proceed with operation }
A pointer makes it clear that it is the identity of the associated mutex that is being queried. A (const-"correct") reference return implies that the purpose of the accessor is to return, well, a reference to the mutex object, presumably so that the client can do something with it.
That would put to rest any questions about mutex() transferring mutex ownership, e.g.:
delete lock.mutex();
I considered bool is_associated_with( Mutex const & m ) const; but that's a bit too much of a handholding for my taste, and doesn't allow us to use mutex() in the Effects clauses. The kind of a person that would delete lock.mutex() would never get a multithreaded program correct anyway.
Now that we got rid of the excess locks, how about doing the same with the mutexes?
That worries me a lot. We need several different flavors of mutex because the more functionality you put into a mutex, the more expensive it is both in terms of size and speed. Why pay for a recursive mutex if you don't need one? Why pay for a timed mutex? But when you need one of these more expensive types, then the price is worth it.
First, please note that I never said anything about mutex being recursive (and the specification says that relocking is undefined behavior). A recursive mutex is a separate entity (and its specification is slightly different). That aside. It is precisely the assertion that (1) a try_mutex is more expensive than a mutex, and (2) that a timed_mutex is more expensive than a try_mutex, that I am challenging. I see no evidence for (1). (2) is more interesting. You will note that POSIX indeed makes you explicitly state whether you want a recursive mutex or not - because recursive mutexes are more expensive. However no such requirement exists for "timed mutexes". Either all mutexes are timed, or they are not. This, for me, indicates that a timed mutex is not more expensive than a try mutex, just that pthread_mutex_timedlock is a late addition to the standard. Do you have data on whether your platforms support pthread_mutex_timedlock?
I can't speak for the boost implementation (haven't carefully studied it), but the Metrowerks implementation also supports conditions operating on a recursive mutex.
Interesting. I presume that this was a deliberate design decision. There is a school of thought that says that a recursive mutex can only be used to sweep bugs under the carpet and is never needed in a correctly designed multithreaded program, which probably applies doubly to conditions operating on a recursive mutex locked more than once. But I'm not qualified to judge.