|
Boost : |
From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2002-08-06 14:48:12
----- 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?
Fernando Cacciola
Sierra s.r.l.
fcacciola_at_[hidden]
www.gosierra.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk