Boost logo

Boost :

Subject: Re: [boost] Boost.Fiber mini-review September 4-13
From: Agustín K-ballo Bergé (kaballo86_at_[hidden])
Date: 2015-09-07 21:18:55


On 9/7/2015 12:52 PM, Agustín K-ballo Bergé wrote:
> On 9/4/2015 12:14 PM, Nat Goodspeed wrote:
>> Hi all,
>>
>> The mini-review of Boost.Fiber by Oliver Kowalke begins today, Friday
>> September 4th, and closes Sunday September 13th. It was reviewed in
>> January 2014; the verdict at that time was "not in its present form."
>> Since then Oliver has substantially improved documentation,
>> performance, library customization and the underlying implementation,
>> and is bringing the library back for mini-review.
>>
>> The substance of the library API remains the same, which is why a
>> mini-review is appropriate.
>
> I had a look at `condition_variable[_any]` documentation, and was
> surprised to see that those two classes are guaranteed to be just
> aliases to a single implementation.

A bit more on the subject, the documentation for `wait()` states:

"Precondition: lk is locked by the current fiber, and either no other
fiber is currently waiting on *this, or the execution of the mutex()
member function on the lk objects supplied in the calls to wait in all
the fibers currently waiting on *this would return the same value as
lk->mutex() for this call to wait."

This seems to come directly from the standard, where it applies only to
`condition_variable` and not `condition_variable_any`. Not only
`condition_variable_any` does not have that precondition, it doesn't
even require `lk->mutex()` to be well-formed. Your implementation
doesn't seem to have those requirements, since (I assume) it works fine
for `condition_variable_any`.

"Note: The Precondition is a bit dense. It merely states that all the
fibers calling wait on *this must wait on lk objects governing the same
mutex."

Fine, sans **currently**...

"Three distinct objects are involved in any condition_variable::wait()
call: the condition_variable itself, the mutex coordinating access
between fibers and a lock object (e.g. std::unique_lock)."

I wouldn't call a "call" an "object", but fine...

"In some sense it would be nice if the condition_variable's constructor
could accept the related mutex object, enforcing agreement across all
wait() calls; but the existing APIs prevent that."

One does not necessarily need to use the same mutex with a single
condition variable over and over again, the requirement applies to
concurrent waiters only (and again only for `condition_variable`).

"Instead we must require the wait() call to accept a reference to the
local lock object."

Indeed you must, since the user will have to do some checks under the
lock before calling `wait()`, and those and the wait must happen
atomically (or else risks forever sleeping).

"It is an error to reuse a given condition_variable instance with lock
objects that reference different underlying mutex objects. It would be
like a road intersection with traffic lights independent of one another:
sooner or later a collision will result. "

This states a different *stronger* requirement than the precondition, so
which is it?

Long story short, as far as I understand `condition_variable` allows for
a more efficient implementation where the lock used to protect the
variable is also used to protect the condition internal structures,
while `condition_variable_any` needs an internal lock of its own. But I
never quite fully understood their differences, and I wasn't present for
the discussion, so perhaps someone else can enlighten us.

Regards,

-- 
Agustín K-ballo Bergé.-
http://talesofcpp.fusionfenix.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk