
Finally getting time to answering this: David Abrahams wrote:
Michael Glassford <glassfordm@hotmail.com> writes:
I had considered this, but there does seem to be some benefit in having separate mutex types, which is what I assume led to there being three mutex types and three lock types in the original design. You've noted these reasons below, but I'll reiterate:
* On pthreads, the timed mutex requires an additional data member, (condition variable) to handle cases when pthreads_timedlock isn't supported.
* On WinNT, the timed mutex operations require a win32 mutex object, while the mutex and try mutex can use a win32 critical section.
* On Win9x, the timed mutex and try mutex operations require a win32 mutex object, while the mutex can use a win32 critical section.
In other words, on the most widely-used platforms, collapsing the mutex types into one imposes some penalty (larger mutex object or more limited implementation options) on users. Also (I ask, not as a hypothetical question, but as a request for information): is there another platform where combining the mutex types incurs a similar or worse penalty?
If the difference is in the code that must be generated within the locking function, I'd guess that the differently-named functions can handle it. If the difference is in the data stored in the mutex and/or the lock, it could be an issue. You might be able to use boost::variant to minimize storage. It would be worth doing some experimentation to see whether optimizers can make the other overheads disappear.
The difference in the pthreads case is a difference in the data that must be stored in the Boost.Threads mutex object: each one needs to store both a mutex and a condition variable, though I suppose--at the expense of requiring the storage to be dynamically allocated--space for the condition variable could be allocated only on platforms that don't support pthreads_timedlock. In the Win32 cases, if you're going to use timed mutex functions (or, on Win9x, try mutex functions), the Boost.Threads mutex object needs to allocate a Win32 mutex object; if not, it can allocate a Win32 critical section. Currently Boost.Threads mutexes objects can tell whether you intend to use try or timed functions by whether you declare a try_mutex or timed_mutex, and allocate the appropriate Win32 synchronization object accordingly. But if all mutex types are combined into one there won't be any way for it to tell, and it will have to allocate a Win32 mutex object always. Another option in the Win32 case, which Peter already mentioned, is to write an alternate implementation of critical sections (such as the one Alexander Terekhov outlined an implementation for) that supports both try and timed functions. If done well, this would be desirable even if the mutex types are not combined. Mike