$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: William E. Kempf (williamkempf_at_[hidden])
Date: 2002-08-06 16:21:25
----- Original Message -----
From: "Fernando Cacciola" <fcacciola_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Tuesday, August 06, 2002 2:48 PM
Subject: Re: [boost] Re: Re: Threads & Exceptions
>
> ----- Original Message -----
> From: "William E. Kempf" <williamkempf_at_[hidden]>
> To: <boost_at_[hidden]>
> Sent: Tuesday, August 06, 2002 4:10 PM
> Subject: Re: [boost] Re: Re: Threads & Exceptions
>
>
> > ----- Original Message -----
> > From: "Fernando Cacciola" <fcacciola_at_[hidden]>
> > To: <boost_at_[hidden]>
> > Sent: Tuesday, August 06, 2002 1:30 PM
> > Subject: Re: [boost] Re: Re: Threads & Exceptions
> >
> >
> > >
> > > ----- Original Message -----
> > > From: "George A. Heintzelman" <georgeh_at_[hidden]>
> > > To: <boost_at_[hidden]>
> > > Sent: Tuesday, August 06, 2002 2:04 PM
> > > Subject: Re: [boost] Re: Re: Threads & Exceptions
> > >
> > >
> > > >
> > > >
> > > > > I don't think so. There's no requirement for return values to be
> > > default
> > > > > constructable, but that's the only manner in which I can see to
> > > implement
> > > > > this. [ Return values from user functions in thread joins ]
> > > >
> > > > I think you can do it with a placement new, using only copy
> > > > constructors:
> > > >
> > > This is the exact mechanism used by the class optional<>, which is in
> the
> > > Files Section, under 'class optional', and which I am currently
brushing
> > up.
> > > optional<> semantics are a bit different, but there is nevertheless
some
> > > similarities and I'd like to consider this context as well.
> > >
> > > I've been only scanning through this discussion so didn't got all the
> > > details of your example: Could you post a more elaborate example,
(with
> > some
> > > more context)?
> > > I want to see the similarities with optional<>.
> >
> > The idea is to templatize boost::thread on the return type, thusly:
> >
> > template <typename R>
> > class thread
> > {
> > public:
> > thread(boost::function0<R> func);
> > // other stuff
> > R join();
> > };
> >
> > Internally the implementation must map to something along the lines of
> > (pseudo code, not anything functional):
> >
> > void proxy(void* p)
> > {
> > data* d = static_cast<data*>(p);
> > d->r = d->func();
> > }
> >
> > thread::thread(function0<R> func)
> > // initialize m_d somehow
> > {
> > create_native_thread(&proxy, &m_d);
> > }
> >
> > R thread::join()
> > {
> > native_join();
> > return m_d.r;
> > }
> >
> > The key is that the native proxy won't support return by value and must
> use
> > an in/out variable instead, but we want the result recorded there to be
> > returned during the call to join(), and we want the whole thing to work
> with
> > only the requirements imposed on return value types. This means the
> data::r
> > will be implemented with some aligned memory buffer and the proxy will
use
> > placement new instead of assignment to "initialize" this buffer with the
> > return value that will later be used by join(). The tricky part of this
> is
> > the portable alignment implementation. This will mean that the value
will
> > be copied twice, but I don't think that's all that important to know.
> >
> > Bill Kempf
> >
> OK, I see.
>
> It seems to me off the top of my head that optional<> could fit in here
> quite nicely.
> Its semantics are (roughly):
>
> optional<T> x ; // uinitialized storage for 'x', default constructor
> bypasssed.
> *x = some_x ; // initialization-assignment.
> T x = *x ; // accessing of assigned value. throws if 'x' has never been
> initialized.
>
> So, your example would look something like:
>
> template <typename R>
> class thread
> {
> public:
> thread(boost::function0<R> func);
> // other stuff
> R join();
>
> struct data
> {
> optional<R> r ;
> } m_d ;
> };
>
> void proxy(void* p)
> {
> data* d = static_cast<data*>(p);
> *d->r = d->func();
> ^ Notice the dereference
> }
>
> thread::thread(function0<R> func)
> // m_d.r default contructor (which is optional<R>' ctor, not R's ctor)
does
> the job without initializing the R.
> {
> create_native_thread(&proxy, &m_d);
> }
>
> R thread::join()
> {
> native_join();
> return *m_d.r;
> ^ Notice the dereference
> }
>
> What do you think?
If the implementation is fully portable and addresses the alignment issues
and does what I think it does from your description, I think it's problem
solved and I'm left with no objections to adding return value semantics.
Bill Kempf