Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2001-06-30 10:09:35


From: <williamkempf_at_[hidden]>

> 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.

> 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.

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.

> 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.

> > 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.

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.

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.

--
Peter Dimov
Multi Media Ltd.

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