$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: williamkempf_at_[hidden]
Date: 2001-06-30 22:27:26
--- In boost_at_y..., "Peter Dimov" <pdimov_at_m...> wrote:
> From: <williamkempf_at_h...>
> 
> > When does a virtual method ever lead to real world time issues? It
> > does, and the C++ language is designed according to this fact, 
even
> > though it may be difficult to give a precise example for when this
> > may be true.
> 
> Actually it is possible to give an example where this is true, but 
I get
> your general point.
> 
> > C++ is a "too the metal" language design, and I think
> > we should try to honor this in our own design.
> 
> The 'zero-overhead' rule is important. I'm not saying anything 
against it.
> I'm simply trying to explain that thread::ref _can_ conform to the
> zero-overhead rule, whereas an explicitly reference-
counted 'thread' cannot.
I'd have to see an implementation that managed this.  I don't see how 
it could, especially since it must retain thread safety.
> > The non-copyable object *is* useful on it's own.  So far all of 
the
> > examples in the Boost.Threads library can be done with a non-
copyable
> > design (though the examples that use loops will require creation 
on
> > the heap, but this doesn't mean ref-counting).
> 
> Creation on the heap is orders of magnitude more expensive than 
managing a
> reference count.
Possibly, possibly not.  There are a lot of memory schemes that can 
be employed to reduce the cost.
However, I should point out that it's *very* likely that some 
implementations are going to need to do both memory allocation and 
ref-counting to implement a thread::ref concept.
 
> This is the major problem I see with a noncopyable design. [This is 
not
> limited to the current discussion, but applies in general.] The 
design
> forces the user to use 'new,' a keyword that has no place in user 
land.
So instead you bury it in the implementation and expect better 
performance?
 
> > Yes, but again this is in keeping with C++ design.  As long as the
> > burden is minimal (it is) then I say go with the more "too the 
metal"
> > design.
> 
> My point is that providing a noncopyable thread and leaving the 
management
> to shared_ptr is actually less efficient than providing a 
thread::ref. You
> have no means to avoid the reference counting overhead of 
shared_ptr because
> you don't have access to the underlying native type.
I still don't see how to get a thread::ref with out overhead (and 
significant overhead at that).
 
> > > A thread::ref can use the fact that the underlying native type 
is
> > > lightweight and copyable for further optimizations (sometimes
> > avoiding heap
> > > allocation altogether); in fact I think that a good 
implementation
> > of
> > > thread::ref need not introduce any noticeable overhead.
> >
> > Nope.  Just like a raw pointer, actual ownership is going to have 
to
> > be tracked.
> 
> Yes, of course. Tracking ownership - on its own - is not 
inefficient.
I know of only a few ways to track ownership:
1.  Ref-counting.  Very slow, especially when made thread safe.  This 
also is very likely to require dynamic memory allocation for at least 
some platforms, adding more overhead.
2.  Linked lists.  Faster, but still slow, and with the need for 
thread safety the overhead remains significant.
3.  Through complex algorithms such as mark-and-sweep.  I'm not sure 
these sort of algorithms would be appropriate for this task.
4.  Manually.  This simply isn't safe enough for most C++ programmers.
 
> Requiring heap allocation in order to track ownership, on the other 
hand, is
> inefficient.
> 
> > There's not any way to take advantage of the fast copy
> > semantics of the native types.
> >
> > > [For instance, a thread::ref can store the native type and 
one/two
> > > thread::ref pointers, using the 'linked shared pointer' idiom.]
> >
> > This is only a variation on ref-counting.  Yes, we can optimize 
the
> > management of references, but we simply can't eliminate the 
overhead.
> 
> What overhead? There's (a minimal) overhead on copy, but you can't 
copy a
> noncopyable object anyway. :-) You only pay for what you use. This
> implementation of thread::ref has no overhead compared to a 
noncopyable
> thread object.
> 
> Pedantically speaking,
> 
> thread::ref r = thread::create(f);
> 
> _may_ introduce a temporary, but its overhead will be swamped by 
the actual
> thread creation.
> 
> Destroying an (unique) thread::ref also involves some minimal 
pointer
> housekeeping but again, this will be dominated by the native call 
that
> releases the resources.
Destroying a non-unique thread::ref also involves overhead, and this 
is not necessarily insignificant.  Copying the thread ref also 
entails overhead, which again may not be insignificant.
 
> So my point is that a good implementation of thread::ref can 
directly
> compete with the 'layer 1' noncopyable thread object and be an 
order of
> magnitude more efficient than 'layer 2' shared_ptr<thread>, while 
at the
> same time being more user-friendly.
I'm not convinced yet.
Bill Kempf