Boost logo

Boost :

Subject: Re: [boost] [thread] using Boost.Thread with move-only arguments
From: Fernando Pelliccioni (fpelliccioni_at_[hidden])
Date: 2013-04-07 18:59:37


On Sun, Apr 7, 2013 at 7:36 PM, Vicente J. Botet Escriba <
vicente.botet_at_[hidden]> wrote:

> Le 08/04/13 00:33, Vicente J. Botet Escriba a écrit :
>
> Le 08/04/13 00:15, Fernando Pelliccioni a écrit :
>>
>>> On Thu, Apr 4, 2013 at 3:19 AM, Vicente J. Botet Escriba <
>>> vicente.botet_at_[hidden]> wrote:
>>>
>>> Le 04/04/13 04:40, Fernando Pelliccioni a écrit :
>>>>
>>>> Hi Vicente,
>>>>
>>>>> I have an issue with Boost.Thread contructor using move-only type
>>>>> arguments.
>>>>>
>>>>> The "Thread Constructor with arguments" section of the documentation
>>>>> says
>>>>> ...
>>>>>
>>>>> template <class F,class A1,class A2,...>
>>>>> thread(F f,A1 a1,A2 a2,...);
>>>>>
>>>>> Preconditions:
>>>>> F and each An must by copyable or movable.
>>>>>
>>>>> http://www.boost.org/doc/libs/****1_53_0/doc/html/thread/**thread_**_**>
>>>>> management.html#thread.thread_****management.thread.multiple_****
>>>>> argument_constructor<
http://**www.boost.org/doc/libs/1_53_0/**
>>>>> doc/html/thread/thread_**management.html#thread.thread_**
>>>>> management.thread.multiple_**argument_constructor<http://www.boost.org/doc/libs/1_53_0/doc/html/thread/thread_management.html#thread.thread_management.thread.multiple_argument_constructor>>
>>>>>
>>>>>
>>>>> "An" could be copyable or movable, but the following example fails to
>>>>> compile...
>>>>>
>>>>> error: use of deleted function 'A::A(const A&)'
>>>>>
>>>>> Sorry, if the documentation is not clear. I should add a link to
>>>>> the
>>>>>
>>>> Move emulation section (http://www.boost.org/doc/**
>>>> libs/1_53_0/doc/html/thread/****emulations.html#thread.****
>>>> emulations.move<http://www.**boost.org/doc/libs/1_53_0/doc/**
>>>> html/thread/emulations.html#**thread.emulations.move<http://www.boost.org/doc/libs/1_53_0/doc/html/thread/emulations.html#thread.emulations.move>>)
>>>>
>>>> for each function having rvalue references if the documentation is not
>>>> clear. Please could you create a Ticket for that?
>>>>
>>>> Which Boost.Thread version are you using? That is, BOOST_THREAD_VERSION
>>>> is
>>>> 2, 3 or 4?
>>>> Could you try by defining BOOST_THREAD_USES_MOVE, BOOST_THREAD_VERSION 3
>>>> or BOOST_THREAD_VERSION 4?
>>>>
>>>>
>>>>
>>>>> I think we should modify ...
>>>>>
>>>>> template <class F,class A1>
>>>>> thread(F f,A1 a1,typename
>>>>> disable_if<boost::thread_****detail::is_convertible<F&,****thread_attributes
>>>>>
>>>>>
>>>>>> ,
>>>>>>
>>>>> dummy* >::type=0):
>>>>> thread_info(make_thread_info(****boost::bind(boost::type<void>**(**
>>>>> ),f,a1)))
>>>>> {
>>>>> start_thread();
>>>>> }
>>>>>
>>>>>
>>>>> ... by ...
>>>>>
>>>>> template <class F,class A1>
>>>>> thread(F&& f,A1&& a1,typename
>>>>> disable_if<boost::thread_****detail::is_convertible<F&,****thread_attributes
>>>>>
>>>>>
>>>>>> ,
>>>>>>
>>>>> dummy* >::type=0):
>>>>>
>>>>> thread_info(make_thread_info(****boost::bind(boost::type<void>**(**
>>>>> ),f,boost::forward<A1>(a1))))
>>>>> {
>>>>> start_thread();
>>>>> }
>>>>>
>>>>> ( In the all family of related ctors in "boost/thread/detail/thread.**
>>>>> **hpp"
>>>>> )
>>>>>
>>>>> But, I don't know if boost::bind is forwarding its arguments
>>>>>
>>>>> No. The problem is that boost::bind doesn't supports move semantics
>>>> (Boost.Move).
>>>>
>>>> I think we should modify Boost.Bind to be similar to std::bind.
>>>>
>>>>> Is there any reason why Bind has not changed so far? Have you found any
>>>>> limitations?
>>>>>
>>>>> IIRC, I requested the feature long-long time ago.
>>>>
>>>>
>>>> If Bind can not be changed, I think Boost.Thread should use some other
>>>>> tool
>>>>> similar to Bind to make forwarding parameters.
>>>>> GCC Libstdc++ use a Bind-lite tool for std::thread.
>>>>>
>>>>> I have taken in account some cases, but not everything works yet. E.g
>>>> the
>>>> prototype that you need is
>>>>
>>>> template <class F>
>>>> explicit thread(BOOST_THREAD_RV_REF(F) f
>>>> , typename disable_if<is_same<typename decay<F>::type, thread>,
>>>> dummy* >::type=0
>>>> );
>>>>
>>>> I suspect that you need to follow the instructions given in
>>>> http://www.boost.org/doc/libs/****1_53_0/doc/html/thread/****>
>>>> emulations.html#thread.****emulations.move.portable<http:**
>>>> //www.boost.org/doc/libs/1_53_**0/doc/html/thread/emulations.**
>>>> html#thread.emulations.move.**portable<
http://www.boost.org/doc/libs/1_53_0/doc/html/thread/emulations.html#thread.emulations.move.portable>>to
>>>> make your class A movable :(
>>>>
>>>> I can work on this if you want.
>>>>
>>>>> What do you think?
>>>>>
>>>>> I'm all for a boost::bind or boost::bind-lite supporting boost
>>>>> semantics
>>>>>
>>>> (using Boost.Move). If you can work on this a propose a patch to boost
>>>> bind
>>>> I'm sure all the Boost community will thank you.
>>>> There are a lot of basic Boost libraries that need an update to support
>>>> move semantics (as Tuple, Fusion, SmartPtr, Exception?) so that other
>>>> libraries can built on them. Any effort on this sens will be much
>>>> appreciated.
>>>>
>>>> Please, let me know if you have some trouble after defining one of the
>>>> following
>>>>
>>>> #define BOOST_THREAD_USES_MOVE
>>>> #define BOOST_THREAD_VERSION 3
>>>> #define BOOST_THREAD_VERSION 4
>>>>
>>>> Best,
>>>> Vicente
>>>>
>>>> ______________________________****_________________
>>>> Unsubscribe & other changes: http://lists.boost.org/**
>>>> mailman/listinfo.cgi/boost<htt**p://lists.boost.org/mailman/**
>>>> listinfo.cgi/boost <http://lists.boost.org/mailman/listinfo.cgi/boost>>
>>>>
>>>>
>>>>
>>> Hi Vicente,
>>>
>>> I had not set BOOST_THREAD_VERSION. I just realized that is set to 2 by
>>> default.
>>> Sorry, I had no idea about Boost Thread Move emulations. I tested the
>>> code
>>> using a C++11 movable-only type and a Boost.Move movable-only type.
>>>
>>> Same compilation error if I define BOOST_THREAD_USES_MOVE and
>>> BOOST_THREAD_VERSION to 3 or 4 ( using Boost Thread Move Emulation )
>>>
>>> #define BOOST_THREAD_USES_MOVE
>>> //#define BOOST_THREAD_VERSION 3
>>> #define BOOST_THREAD_VERSION 4
>>>
>>> #include <iostream>
>>> #include <boost/thread.hpp>
>>>
>>> struct A
>>> {
>>> BOOST_THREAD_MOVABLE_ONLY(A)
>>>
>>> A() {}
>>>
>>> void run() { }
>>> };
>>>
>>>
>>> void f( A a )
>>> {
>>> a.run();
>>> }
>>>
>>> void exec_boost()
>>> {
>>> A a;
>>> boost::thread t( f, std::move(a) );
>>> t.join();
>>> }
>>>
>>> error: use of deleted function 'A::A(const A&)'
>>>
>>> I'll wok on Boost.Bind trying to make it move-enabled.
>>>
>>> Thank you for your dedication and patience.
>>>
>> You are welcome.
>>
>> Could you try with
>>
>> class A : public noncopyable
>> {
>> BOOST_THREAD_MOVABLE_ONLY(A)
>>
>> public:
>> A(int ) {}
>>
>> A(BOOST_THREAD_RV_REF(A) ) {}
>>
>> A& operator=(BOOST_THREAD_RV_REF(**A) ) { return *this;}
>>
>> };
>>
>> BOOST_THREAD_DCL_MOVABLE_BEG(**T) A BOOST_THREAD_DCL_MOVABLE_END
>>
>>
>> Sorry I meant
>
>
> BOOST_THREAD_DCL_MOVABLE(A)
>
>
> Vicente
>
>
>
> ______________________________**_________________
> Unsubscribe & other changes: http://lists.boost.org/**
> mailman/listinfo.cgi/boost<http://lists.boost.org/mailman/listinfo.cgi/boost>
>

Hi Vicente,

Same error...

//Begin code ------------------------------------------------------
#define BOOST_THREAD_USES_MOVE
//#define BOOST_THREAD_VERSION 3
#define BOOST_THREAD_VERSION 4

#include <boost/thread.hpp>

class A : public boost::noncopyable
{
    BOOST_THREAD_MOVABLE_ONLY(A)

public:
    A( int ) {}

    A(BOOST_THREAD_RV_REF(A) ) {}
    A& operator=(BOOST_THREAD_RV_REF(A) ) { return *this; }

    void run() { }
};

//BOOST_THREAD_DCL_MOVABLE_BEG(T) A BOOST_THREAD_DCL_MOVABLE_END
BOOST_THREAD_DCL_MOVABLE(A)

void f( A a )
{
    a.run();
}

void exec_boost()
{
    A a(1);
    boost::thread t( f, std::move(a) );
    //t.join();
}

//End code ------------------------------------------------------

The error occurs in
boost/thread/detail/thread.hpp
line 389
Trunk revision 83652

                 template <class F,class A1>
                 thread(F f,A1 a1,typename
disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >,
dummy* >::type=0):
    line 389:
 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
                 {
                     start_thread();
                 }

parameter a1 is not a BOOST_THREAD_RV_REF(A1) and is not moved.

I think it should be:

                 template <class F,class A1>
                 thread(F f, BOOST_THREAD_RV_REF(A1) a1,typename
disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >,
dummy* >::type=0):
    line 389:
 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,
boost::move(a1) )))
                 {
                     start_thread();
                 }

But in this case the error will occur within Boost.Bind

Thanks and regards,
Fernando.


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