Boost logo

Boost :

From: williamkempf_at_[hidden]
Date: 2001-08-19 10:30:22


--- In boost_at_y..., John Max Skaller <skaller_at_m...> wrote:
> William Kempf wrote:
> >
> > We're nearing the date slotted for submission of Boost.Threads,
but there
> > are still a couple of design issues that I need to work out. So,
I'm coming
> > here one final time for opinions. I *think* I know what to do in
each case,
> > but I want to see if I'm missing something.
> >
> > The first is the thread specific storage concept. My final
design is the
> > following:
> >
> > template <typename T>
> > class thread_specific_ptr : private noncopyable
> > {
> > public:
> > thread_specific_ptr();
> >
> > T* get() const;
> > T* operator->() const;
> > T& operator*() const;
> > T* release();
> > void reset(T* p=0);
> > };
> >
> > This is similar to std::auto_ptr<> in it's interface, though the
type is
> > non-copyable. When a thread is created it's thread specific
instance is
> > initialized to 0, so the first time get() is called it will
return 0. For
> > this reason calling operator->() and operator*() may be
dangerous. Given
> > this and the fact that these operations are expensive enough that
most
> > usages will probably use get() instead and cache the value, I'm
wondering if
> > the smart pointer operations should even be included?
>
> Yes. The reason is: templates depend on syntax. When using
> templates, you don't always have the choice of first calling get(),
> then using the temporary. For a similar reason, it makes sense to
> allow simple comprehensible code to be written, even if it isn't
> the most efficient, because often efficiency is irrelevant
> and maintainability is a high priority.
>
> []

Valid. I'm satisfied with this interface then.

> > Comments?
>
> Well specified. As to the new join semantics:
> I have some concern that at one place you argue for the
> strongest semantics, whereas elsewhere you support
> thread local storage -- which is a hack -- and consider
> adopting threads.

TLS may be a "hack" but it's necessary. And adopting threads is
basically necessary as well. Imagine the following code:

class foo
{
   void bar() { if (thread() == m_thread) ... }
};

If Boost.Threads can't "adopt" threads not created within the library
the above code can easily produce undefined behavior. At least the
latest design reduces the complexity of adoption since the thread
object created through thread() is valid only within the thread of
execution in which it was created.

> If you adopt threads, and use TLS,
> then there could well be a 'backwards compatibility
> reason' for several threads to join another -- for
> example, you said yourself you have done this.

I've done this with out any actual thought to the difference between
waiting for "full thread termination" and simply waiting for some
STATE. It's trivial to do the latter with a TLS instance of
a "monitor".

> Now suppose you had to adopt those threads -- i.e. you didn't
> have further control over the thread func than 'porting',
> then you might have to allow several threads to join another.

No, you have to allow the threads to wait for the thread to finish,
not for them to "join". Who ever created the threads being adopted
would be responsible for "joining" them.
 
> Ideally, you could separate 'hacks' like TLS
> and adoption, from 'top level pure boost threads',
> with which new well principled designs could be constructed.
> [Is there a way to do this using, for example, an extra
> namespace?]

One of us isn't understanding the other here, so I can't comment on
this. Sorry.

Bill Kempf


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