Boost logo

Boost :

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


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