Boost logo

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