Boost logo

Boost :

Subject: Re: [boost] [thread] Use of synchronized_value<> member in a constructor
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2013-06-17 01:26:22


Le 17/06/13 01:36, Klaim - Joël Lamotte a écrit :
> On Sun, Jun 16, 2013 at 11:54 PM, Vicente J. Botet Escriba <
> vicente.botet_at_[hidden]> wrote:
>> I was wondering if a not yet existing synchronized_value<T&> could help in
>> your context.
>> You would need to declare a value and a reference.
>>
>>
>> explicit Sequence( SequenceInfo info )
>> : m_value( info ), m_ref(M_value)
>> {
>> m_value.do_something(); // no need to lock.
>>
>> }
>>
> It's closer to the ideal but I think it defeats the point of having only
> one way to access the member
> after the constructor is called.
Right. The constructor of the instance could master the access to the
unsynchronized value. It is similar to the wrapper solution.

class SequenceImpl
{
   X m_value1;
   Y m_value2;
public:
   synchronized_value<X> m_ref1; // only the synchronized parts are public.
   synchronized_value<X> m_ref2;
   SequenceImpl(SequenceInfo info)
   : m_value1(info), m_value2(info),
     m_ref1(m_value1), m_ref2(m_value2)
   {
     // Do whatever you want with m_value1, m_value2 without locking.
   }

};

class Sequence : public SequenceImpl
{
public:
   Sequence(SequenceInfo info) : SequenceImpl(info)
   {
   }
};

Some measures would be needed to ensure that there is no lost of
efficiency while using a reference instead of a value in synchronized_value.
>
> But the mix of this suggestion and my previous one reminded me unique_lock:
> you can
> not lock on construction with it. Maybe something similar could be done?
> So maybe something like that would work:
>
> explicit Sequence( SequenceInfo info )
> : m_value( info , synchronized_value::dont_lock_yet ) // optional
> {
> m_value->do_something(); // don't lock!
> ...
> m_value.begin_sync(); // (random name) from here the usual locking is
> mandatory to access the value.
>
> m_value->do_something(); // locking
> }
>
> void do_something()
> {
> m_value->do_something(); // locking
> m_value.begin_sync(); // throw exception or UB or nothing?
> }
>
> I'm not sure if it would require changing the mutex concept though, but if
> it can be done with the current default one
> it would allow beginning the protection explicitly when needed but not
> removing it once it's active.
> Maybe just an atomic bool saying if the sync should happen or not, but then
> it's an additional test on access and with reading an atomic,
> which I have not a clear idea if it's expensive or not. Or maybe it would
> be a specialization.
>
> What do you think?
>
This will make the whole lifetime of the instance less efficient, so
globally you will lost efficiency.

I don't think it is worth the effort to change anything.
* The lost of efficiency should be minor and only on the constructor
when the user can not use a factory (the type T is not copyable nor
movable).
* The solutions make the design must more complex.

Best,
Vicente


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