Subject: Re: [boost] Boost sprint: #3407 boost::call_once not re-entrant (at least in win32)
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2009-11-23 09:55:32
On Mon, Nov 23, 2009 at 9:46 AM, Gottlob Frege <gottlobfrege_at_[hidden]> wrote:
> On Mon, Nov 23, 2009 at 6:46 AM, Anthony Williams <anthony.ajw_at_[hidden]> wrote:
>> Gottlob Frege <gottlobfrege_at_[hidden]> writes:
> You can also solve it by using what I call a 'branding gate' - the
> gist of it at least, from memory: as each thread enters, it increments
> a waiting count and/or the 'running' flag (lo/hi halves of an int,
> say). But on retry (after an exception) you don't just reset the
> running flag, you increment it - and 'running' becomes whether the
> flag is odd or even. This way every entry or wait is 'branded' with a
> unique value. You can then use the unique value to look up a named
> mutex (or named event). Windows takes care of ref counting for you.
> You still end up creating a global named handle, but it can be
> deferred until contention is detected.
To be more clear: the 'running' half is more of an 'attempt' half.
And that half is used as the unique value. So first thread comes in,
finds 'running' to be 0, sets it to 1. All other threads increment
waiting half. On exception, running becomes 2 (ie reset to 'retry').
Next thread in (maybe old waiter) sets running to 3. Waiting half can
actually be reset to 0 at this point as it can be stored locally, at
this point I think, although I'd have to look into it. And/or the
global named event is ref counted and you don't really need to worry
about the waiting count anymore. Something like that.
Anyhow, it is only the 'running' half that is used as the unique-ifier
for each attempt. Obviously if the whole branding gate was used,
everyone would have their own event!