From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2007-08-26 18:38:34
Andrey Semashev wrote:
> Hello Tobias,
> Sunday, August 26, 2007, 1:37:17 PM, you wrote:
>>> Hmm, I'm not sure of the purpose of this project. Is it supposed to
>>> pass several tools under its umbrella to boost via fast-track review?
>> Sort of. It's just an idea, so far.
>> Its purpose is to avoid lots of fast-track reviews (and reviewing
>> overhead) for utility components by grouping them into a "pseudo
>> library", thus encouraging developers to brush up / factor out useful
> In this particular case the tool will be reviewed during the Boost.FSM
> review (if it will, since it's not for public use anyway), so
> including it in X-Files won't reduce the amount of reviews. On the
> other hand, if Boost.FSM is rejected but there is interest to this
> tool, I would gladly extract it to the X-Files project.
If your library gets accepted, LWCO is accepted as an implementation
detail. AFAIK you need at least a fast-track review to make it a public
thing (not sure that's what you want, though).
However, I'd at least very much welcome a test suite for LWCO.
>>> Yes, but consider that this code will be executed only once. The rest
>>> of the execution time this mutex is useless.
>> Consider the deadlock if 'once' is used recursively to initialize
>> different resources...
> The mutex is recursive.
Sorry, missed it.
>> Further, it's quite unintuitive that a trivial initialization might get
>> slowed down by one in another thread that takes a lot of time.
>> You can call 'pthread_mutex_destroy' once you're done with the mutex to
>> free up eventually acquired system resources.
> I'll think of it. The first thing that comes to mind is that I'd have
> to count threads that are hanging locked in the mutex since destroying
> it right away would leave those threads in undefined behavior.
It might be possible to use the flag for the counter...
>>>> Also, some platforms will not call 'mutex_destroyer' within a dynamic
>>>> library (you probably know)...
>>> No, I'm not aware of this. Could you elaborate, please? Which
>>> platforms are those?
>> No ctors/dtors are run in static context for shared libraries on most
>> UNIX platforms.
> That's quite a surprise for me. I didn't encounter such behavior on
> Linux (Red Hat). Do you have any workaround for this? I'm thinking of
> GCC-specific attributes for this purpose, but that's one step away
> from portability.
AFAIK there's not much one can do about it except for adding a function
for explicit disposal.
>>> The fundamental problem arises here - I need to safely create a
>>> synchronization object. Non-POSIX APIs don't provide things like
>>> PTHREAD_MUTEX_INITIALIZER or I didn't find them in the docs.
>> I see. Would it be an option to use 'yield' instead of 'sleep'?
> The "yield" function is not guaranteed to switch execution context, it
> may return immediately. If a lower-priority thread entered once
> functor, you may spin for a relatively long time in a "yield" loop
> instead of just letting the lower-priority thread finish its job.
I figured something like that. Does 'Sleep' guarantee preemption - or
does it depend on the argument and the resolution of the system timer?
>>>> For some platforms (such as x86) memory access is atomic, so atomic
>>>> operations are just a waste of time for simple read/write operations as
>>>> the 'is_init' and 'set_called' stuff.
>>> The point is not only in atomic reads and writes, but in performing
>>> memory barriers too. Otherwise the result of executing the once
>>> functor could not have been seen by other CPUs.
>> Then the memory barriers will suffice for x86, correct? As this code is
>> executed on every call, any superfluous bus-locking should be avoided.
> Actually, I got the impression that barriers themselves do a major
> deal of performance impact. Besides, not all compilers support barrier
>> Alternatively, doing an "uncertain read" to check whether we might need
>> initialization before setting up the read barrier might be close enough
>> to optimal.
Bad wording on my side. Substitute "Alternatively" with "Additionally".
> Well, that's a tricky point. I'm not an expert in threading issues,
> but it's not obvious to me whether a memory barrier should act
> regardless of its scope. For example:
> void foo(int& x, int& y)
> if (x == 0)
> y = 10;
> x = 1;
> // use y
> Now, is it guaranteed that those barriers are in effect regardless of
> x value? I think not. Either the compiler may reorder statements in
> such way that y is used before the "if" statement, or the same thing
> may be done by CPU since the barrier instructions may not be executed.
That's not quite what I meant:
// 'initialized' started being false
// 'initialized' is true for sure
// we can't know 'initialized' is still false, so let's
// synchronize and check again
// 'initialized' is true
// 'initialized' is false
Now we only have to cross the bsrrier during (and immediately after)
>>> Well, you may be right here. I could try to reduce memory allocations
>>> in error handling.
>>> But the only possible problem I see there is memory depletion. In such
>>> case you'll get std::bad_alloc which adheres the declared interface of
>>> the implementation. So, strictly speaking, if you have enough memory
>>> you get a detailed error description. If not, you get bad_alloc.
>> Depending on 'lexical_cast', 'iostream' and 'string' still slightly bugs
>> me, though.
> Ok, I'll change the code that formats the error string not to use
> lexical_cast. But it will still depend on std::string since it's in
> the exception class.
Getting rid of 'lexical_cast' and 'iostream' seems good savings, already...
>> Another potential issue: It seems Win32 and MacOS variants are currently
>> not exception-safe. That is, the initialization routine isn't rerun if
>> it has thrown the first time 'once' was called.
> Yep, thanks for spotting that. I'll fix that in a couple of days and
> update the library archive in the Vault. I'll post here a notification
> when it's done.
Looking forward to it!
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk