Boost logo

Boost :

Subject: Re: [boost] [thread] countdown_latch
From: Gaetano Mendola (mendola_at_[hidden])
Date: 2013-05-26 16:45:26


On 26/05/2013 22.01, Vicente J. Botet Escriba wrote:
> Le 26/05/13 19:20, Gaetano Mendola a écrit :
>> On 26/05/2013 17.30, Vicente J. Botet Escriba wrote:
>>> Le 26/05/13 15:07, Gaetano Mendola a écrit :
>>>> On 26/05/2013 09.53, Vicente J. Botet Escriba wrote:
>>>>> Le 25/05/13 15:51, Gaetano Mendola a écrit :
>>>>>> On 25/05/2013 15.26, Vicente J. Botet Escriba wrote:
>>>>>>> Le 25/05/13 14:45, Gaetano Mendola a écrit :
>>>>>>>> On 21/05/2013 07.13, Vicente J. Botet Escriba wrote:
>>>>>>>>> Le 20/05/13 22:09, Gaetano Mendola a écrit :
>>>>>>>>>>
>>>>>>>>>> What's the plan for this countdown_latch is it candidate to be
>>>>>>>>>> included
>>>>>>>>>> in version 1.54 ?
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>> No, documentation and tests are missing. I hope it will be
>>>>>>>>> ready for
>>>>>>>>> 1.55. This and other addition will be experimental and its
>>>>>>>>> interface
>>>>>>>>> will be subject to some changes.
>>>>>>>>> E.g. I have not decided yet how to provide cyclic latches.
>>>>>>>>
>>>>>>>> Given the fact I have my own implementation of a latch, can you
>>>>>>>> please
>>>>>>>> explain what a cyclic latch is, to see if my latch already provide
>>>>>>>> the feature. I will propose my implementation of latch.
>>>>>>>>
>>>>>>>>
>>>>>>> boost::barrier resets the counter once all the threads
>>>>>>> synchronize, so
>>>>>>> that the barrier can be reused again. In order to do that the
>>>>>>> barrier
>>>>>>> store the initial counter value and reuse it at each cycle.
>>>>>>>
>>>>>>> I don't know if I all the latched must support this feature
>>>>>>> (possibly by
>>>>>>> a configuration parameter) or if it is better to have a separated
>>>>>>> cyclic_latch.
>>>>>>
>>>>>> So what are you proposing is a latch that as soon have reached 0 it
>>>>>> will
>>>>>> reset to the initial value and permitting a wait to continue without
>>>>>> stopping if it arrives after the reset or to block waiting for a
>>>>>> reset.
>>>>>> My latch doesn't provide such feature, but isn't enough to keep a
>>>>>> counter (reset_counter) increased at each reset and decreased at each
>>>>>> wait() (before exiting from it). This way the wait shall be a
>>>>>> blocking
>>>>>> call if the "reset counter" is > 0.
>>>>>>
>>>>>> I would make two different names: latch and cyclic_latch
>>>>> Thanks for your advice.
>>>>> The alternative is to have a bool parameter on the constructor and
>>>>> make
>>>>> use of a "restore counter" when "reset counter" is > 0 which is not
>>>>> too
>>>>> expensive. This needs however to store another integer for the
>>>>> "restore
>>>>> counter". I want to be sure that this doesn't adds any additional
>>>>> constraint to the class.
>>>>>>
>>>>>> I'm also to remove the precondition counter > 0 on the
>>>>>> latc::count_down.
>>>>>>
>>>>> I don't see yet the case of a thread using countdown several times the
>>>>> same latch as a valid use case. But maybe if you post a concrete
>>>>> (real)
>>>>> example, it could make me change.
>>>>
>>>> Do you really need a real example?
>>>>
>>> Yes. As having a real example we could see if the solution you propose
>>> would be used by the user or if it would implement its own class to
>>> solve the problem more efficiently.
>>>> I don't have a real example but again, having two threads calling
>>>> latch::count_down on the same latch instance is going to be an headache
>>>> for the user, immagine a multi producer/single consumer application
>>>> where the consumer as to start when at least N items are ready.
>>> I will not use a latch for that. I would build a at least n messages on
>>> the queue data type and use the usual wait on this queue.
>>
>> If the buffer is a general purpose buffer the wait on it will return as
>> soon someone puts stuffs on it. As you know there are multiple way to
>> achieve the same even without the usage of latch.
>>
>> I'm fine with leaving the precondition after all people have to read
>> the manual, I have also see you have added a BOOST_ASSERT( count_ > 0).
> Great.
>>
>> About the cyclic_latch instead of the bool to drive the counter reset
>> I would template the latch using two different policies for reset or
>> not, then I would expose a typedef of it, something like this:
>>
>> template <class COUNTER_POLICY>
>> class Latch {
>>
>> bool count_down(unique_lock<mutex> &lk)
>> /// pre_condition (count_ > 0)
>> {
>> BOOST_ASSERT(count_ > 0);
>> if (--count_ == 0)
>> {
>> counter_policy_.reset(count_);
>> ++generation_;
>> lk.unlock();
>> cond_.notify_all();
>> return true;
>> }
>> return false;
>> }
>>
>> private:
>> COUNTER_POLICY counter_policy_;
>> };
>>
>>
>> typedef Latch<NoResetPolicy> latch;
>> typedef Latch<ResetPolicy> cyclic_latch;
>>
>>
>
> Would the base Latch class be public? if not, this is an implementation
> detail and is equivalent to having two classes but sharing a common
> implementation.

Well, not equivalent because with let say a boolean as parameter you
need to check at runtime what to do (reset the counter or not) this way
with a policy the choose is made a compile time, also implementing it
with a boolean will force you to store anyway the original counter
value, NoResetPolicy to the other side will be an empty class.

> Shouldn't the base latch make use of EBO?

Interesting indeed this should even save that 1 byte in case of
NoResetPolicy.

Regards
Gaetano Mendola


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