Re: MT Design Question
"Scott Meyers" <NeverRead@aristeia.com> wrote in message
news:i5266m$f53$1@news.albasani.net...
Scott Meyers wrote:
?? Tiib wrote:
I do not know if C++0x contains a semaphore of some sort but i imagine
that it is possible to construct one with mutexes as well.
C++0x has no semaphore type, nor, from what I can tell, does pthreads,
TBB or Boost.Thread. My sense is that the preferred thread communication
mechanism in these libraries is condition variables.
Digging a little further, I came across this from Anthony Williams in a
thread from last October:
Currently there is no good way, other than condition variables and
mutexes.
[...]
I can certainly see the benefits of standardizing a lightweight
mechanism such as a semaphore or event count or even a futex, but that
will have to wait for TR2 as it is currently far too late for getting
new proposals in for C++0x.
So it looks like condvars are the "standard" C++0x way of communicating
events between threads.
In the meantime, I'd been wondering about the idea of writing my own mutex
that didn't actually do any locking, using that in conjunction with a
condition variable in an attempt to reduce the cost of that approach.
Anthony had already been there.
Humm... Not exactly sure what your getting at here. I know that an
eventcount allows one to skip a mutex around the "predicate". What advantage
does this idea have over it?
WRT condvar, IIRC, you need that mutex in order to correctly synchronize
wait generations with the predicate.
In the same message, he wrote:
Well, std::condition_variable_any only requires a "lockable" object, so
you could pass a class that implements lock/try_lock/unlock as empty
functions. However, the implementation probably just uses an internal
mutex in this case, so you don't necessarily gain anything.
Am I correct in assuming that the internal mutex would be for the
condition variable and would be used to help manage the data structure
keeping track of which threads were blocked on the condvar?
I think that condvar wait generations are "synchronized" in a sense with the
user predicate because the condvar impl atomically unlocks the user mutex
and waits on the condition. A condvar can be implemented in many different
ways. A condvar internal waiting logic can be based on futexs.
If so, wouldn't using a no-op mutex type eliminate any cost that would be
associated with acquiring the (uncontended) mutex used in conjunction with
the condvar (i.e., the mutex passed to the condvar)? My understanding is
that the cost of such acquisition is low on some platforms, but not so low
on others.
Still not sure what you are getting at. Can you show me a simple example of
how the no-op mutex can be used? Here is general pattern for eventcount:
___________________________________________________
static eventcount g_ec;
static lock_free_queue g_queue; // 100% lock-free queue
// producer
g_queue.push(new node());
g_ec.signal();
// consumer
node* n;
while (! (n = g_queue.try_pop())) // try op
{
eventcount::key const k = g_ec.get(); // get wait key
if ((n = g_queue.try_pop())) break; // try again!
g_ec.wait(k); // wait on the key.
}
// `n' now contains a popped node!
___________________________________________________
The cool thing about this is that `lock_free_queue' has no notion of
conditional waiting. The eventcount "transforms" it into a conditional,
waitable, algorithm.