|
Boost : |
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk