Boost logo

Boost Users :

Subject: Re: [Boost-users] [Thread] 1.53 fails to compile working code
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2013-02-10 05:08:00


Le 09/02/13 00:41, Vicente J. Botet Escriba a écrit :
> Le 09/02/13 00:13, Jeffrey Lee Hellrung, Jr. a écrit :
>> On Fri, Feb 8, 2013 at 1:31 PM, Vicente J. Botet Escriba
>> <vicente.botet_at_[hidden] <mailto:vicente.botet_at_[hidden]>> wrote:
>>
>> Le 08/02/13 19:01, Jeffrey Lee Hellrung, Jr. a écrit :
>>> On Thu, Feb 7, 2013 at 11:46 PM, Szymon Gatner
>>> <szymon.gatner_at_[hidden] <mailto:szymon.gatner_at_[hidden]>> wrote:
>>>
>>> 2013/2/8 Jeffrey Lee Hellrung, Jr.
>>> <jeffrey.hellrung_at_[hidden]
>>> <mailto:jeffrey.hellrung_at_[hidden]>>:
>>> >
>>> > This looks like an error in the future_traits<T>::init
>>> overload set...it's
>>> > missing an overload that a T const & can bind to (in the
>>> second argument).
>>> >
>>> > Also, I think it would be an improvement if
>>> set_value_at_thread_exit was
>>> > able to catch rvalues as emulated rvalue references (when
>>> true rvalue
>>> > references are unavailable) rather than as
>>> lvalue-reference-to-const.
>>> >
>>>
>>> Yes indeed, there is an overload resolution ambiguity.
>>>
>>>
>>> Strictly speaking, it isn't an ambiguity that's causing the
>>> compiler failure, it's that the eligible overload set is empty.
>> You are right.
>>>
>>> I guess movable
>>> / emulation stuff in Thread is more difficult to manage since it
>>> maintains 2 move emulations (original one from Thread and Move).
>>>
>>>
>>> Yes :( I can imagine the maintenance nightmare for Vicente.
>> I don't know if I've missed something really relevant of
>> Boost.Move, but only with this emulation I have a lot of
>> difficulties as not only Boost.Thread defines Movable types, but
>> it offers interfaces with functions that can be movable and that
>> accept copyable/movable arguments and that can return movable types.
>>>
>>> Move
>>> already provides BOOST_RV_REF(T) macro which is T&& on
>>> compiler that
>>> support it and rv<T>& when emulating and this imho is the
>>> argument
>>> type future_traits<T>::init() should use to disambiguate.
>>>
>>>
>>> Ideally, but the present implementation of
>>> set_value_at_thread_exit precludes init capturing by rvalue
>>> reference, AFAICT.
>> Jeffrey I believe the problem comes from the fact that I have
>> added two overloads for set_value_at_thread_exit and the copy
>> overload is instantiated when using a move-only class
>>
>> void set_value_at_thread_exit(const T & result_){...}
>> // this instantiation with a MoveOnly class results in a compiler
>> error
>> void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T)
>> result_){...}
>>
>>> Is the original move emulation even still needed in Thread code.
>>>
>> Using Boost.Move is some kind of breaking change respect to the
>> old one. I'm fully for discarding the old emulation, but I would
>> like to hear what others thing.
>>>
>>> I think there are subtle differences, perhaps not all of which
>>> have been worked out or discovered yet.
>>>
>>>
>> I don't think the problem comes from trying to manage 2 move
>> emulations, but of course I might be wrong.
>>
>> anyway, I will see if I can fix it or otherwise I would restraint
>> the use of _at_thread_exit functions to the compilers supporting
>> them completely.
>>
>>
>> Vicente, here's some tips on how to improve the robustness of the
>> code when compiling without rvalue references (i.e., C++03):
>>
>> If you know a function is going to receive only lvalues or *emulated*
>> rvalue references, it's sufficient to use a T & parameter:
>> [[template< class T > void f(T & x);]] (Just be careful you don't
>> accidentally move x; you may need to wrap some uses of x as
>> [[as_lvalue(x)]] to avoid that.) This is the appropriate case for
>> functions that receive results of boost::forward; I think
>> future_traits::init falls in this category.
>>
>> If a function is designed to accept both lvalues *and* rvalues *of an
>> a priori known type T*, and you want to be able to capture rvalues by
>> emulated rvalue reference (when appropriate), then you need have 2 cases:
>> - T is not Boost.Move-enabled: 1 overload is probably sufficient (if
>> you don't care about constness): [[void f(T const &);]]
>> - T is Boost.Move-enabled: 2 overloads are necessary: [[void f(rv<T>
>> &);]] and [[template< class U > void f(U &);]]
>>
>> Lastly, if a function is designed to accept both lvalues and rvalues
>> of *any* type, and you want to be able to capture any rvalue by
>> emulated rvalue reference when possible, you need 3 overloads, and
>> even then it's not always possible (if the function return type
>> depends on the parameter type, you're probably SOL). This is much
>> more involved, so I won't go into detail here, as I think the issues
>> relevant to this thread fall into one of the two cases above.
>>
>> If you want more detailed help (e.g., patches), we can take this offline.
>>
>>
> Hi,
>
> I have reached to make it compile, but I suspect that there is yet a
> race condition as the test fail/pass randomly.
>
> See attached the patch.
>
> Jeffrey any help on this will be really welcome. Contact me offline if
> you get something.
>
>
I have made some updates to future.hpp and now the two tests work
correctly. I don't know if all the modifications are absolutely needed.

Please, could you give it a try?

Thanks,
Vicente





Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net