From: Howard Hinnant (howard.hinnant_at_[hidden])
Date: 2007-08-21 13:08:19
On Aug 20, 2007, at 7:37 PM, Peter Dimov wrote:
> Howard Hinnant wrote:
>> I realize that this is stricter than POSIX, however I'm not sure that
>> the difference in strictness has a practical consequence. We're
>> talking about a condition which would be waited on with mutex1 by a
>> group of threads, and then at some later date (synchronized properly
>> so as not to overlap) waited on with mutex2. Do you have motivating
>> use cases needing this functionality?
> No, but I also have no motivating use cases needing the check when the
> condition has been default-constructed.
>> As far as overhead goes, I'm more concerned about space overhead than
>> performance overhead. On Mac, sizeof(pthread_cond_t) is 28, and
>> sizeof(pthread_mutex_t) is 44. I would really like for there to be
>> an option for sizeof(std::condition) to be as close to 44 as
>> possible. Consider:
>> class MyClass
>> std::tr2::upgrade_mutex mut_;
>> MyClass already has two std::condition's buried under the
>> upgrade_mutex (at least by my reference implementation).
> I believe that the main cost of a mutex or a condition is measured
> in kernel
> objects, not bytes. One will typically run out of kernel memory much
> earlier, IMO.
I'm not concerned about running out of memory. I'm concerned about
generating more L1 cache misses. As long as the speed of CPU's
outstrips the speed of memory, smaller is very often better. I'm
aware of entire major organizations that compile with -Os when they
want speed, instead of -O3. Size matters, at least for a significant
number of clients.
We have several opposing use cases we need to satisfy with
1. Minimum size - performance overhead.
2. The freedom to dynamically associate mutexes with condition
3. The ability to apply run time check consistency concerning the
4. The ability to wait on general mutex / lock types.
#1 I justified in the previous paragraph.
#2 is new to my list, and reflects your use case suggested with the
default constructor. I believe use of pools for mutexes and/or
condition variables might be a sufficiently motivating use case for #2.
#3 is the opposite of #2. I believe that the use of condition
variables is sufficiently error prone and hard to debug for common use
cases that this is a desired feature.
#4 is arguably the opposite of #1. And I believe it is also a
desirable feature as outlined in several use cases in my "faq", and
supported by the existence of Vista's ability to wait on a read/write
mutex locked in either mode.
std::condition is going to be a core building block to libraries.
User-written std::condition replacements will be, at best, difficult
to write. The interaction of std::condition::wait and thread
interruption is something that intimately ties std::condition to the
details of the rest of the std::threading library. This is unlike
mutexes and locks which I anticipate can fairly easily be replaced or
adapted by user-written code. Therefore I believe we need to make
every effort to satisfactorily meet all of the use cases above.
I believe my current prototype meets all four use cases:
2. std::condition<std::unchecked<std::mutex>> and
std::condition<std::unchecked<Mutex>> // Mutex is general
3. std::condition<std::mutex> and std::condition<Mutex>
As for the default constructor, I have no strong feelings as to what
its semantics should be. In fact at first I didn't even have a
default constructor. I added it fairly late in the game on the belief
that someone would violently object if it weren't there.
I don't object to different syntax in meeting #1 and #2 (in
principle). However I do object to not having a way to address either
of those two cases (especially #1 obviously).
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk