From: Anthony Williams (anthony_w.geo_at_[hidden])
Date: 2005-09-08 10:45:19
"Greer, Joe" <jgreer_at_[hidden]> writes:
> I have continued to think about the call_once() mechanism because many
> uses I can think of for it could require that it be called a lot.
> Therefore, I think we want the "normal" path to be as quick as possible.
> To that end, I was trying to come up with a way to use critical sections
> instead of named semaphores for the guard. I think I have managed that
> now, but it also occurs to me that we can test the flag up front to see
> if it has been set and if it has, we don't need to get any sort of
> guard. In the case that it hasn't, we can then acquire a guard (of some
> sort), re-test the flag (in case we have two threads running in
> parallel), and then execute the function. It looks a little uglier
> because of the double test, but it would execute faster because most of
> the time it would never have to get the guard. Hopefully there is
> something useful here. :)
Thanks, Joe. That's pretty much the technique used by the version I committed
to CVS, except that it uses a mutex rather than a critical section. Having the
initial check prior to acquiring the mutex dramatically speeds up the "happy
path", by a factor of about 100.
The benefit of using a mutex rather than a critical section is
twofold. Firstly the mutex is specific to the once_flag, rather than shared
between all once_flags that invoke the same template specialization, and
secondly it eliminates the possibility of priority inversion problems ---
Sleep(0) does not yield correctly under all circumstances, and can therefore
lead to this thread always running, whilst the thread with the lock doesn't
get any work done, so can't release it.
-- Anthony Williams Software Developer Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk