Boost logo

Boost :

From: Kevlin Henney (kevlin_at_[hidden])
Date: 2000-12-01 06:09:17


In message <906dmn+bo7q_at_[hidden]>, William Kempf <sirwillard_at_my-
deja.com> writes
>> As an aside, if you take this from a function object perspective
>then
>> proper copying semantics are the ones that make immediate sense. The
>> question of reference counting for sharing semantics becomes
>unasked.
>
>I'm not sure I follow this. Taken at face value here I'd have to
>disagree with you because this is a very specific class of function
>objects, aka a polymorphic function object used to wrap generic
>function objects for use in code that can't be rely on template
>typing. As such I don't know if ref-counting semantics aren't
>appropriate.

Ah, but I _do_ know they aren't appropriate ;->

The design principles involved are cohesion, orthogonality and cohesion,
and we can come at this from three different perspectives:

(1) A polymorphic function object that wraps generic function objects
does not imply sharing. By its very description it is intended to be
like a function object. These things don't share (or appear to share)
their representation unless they are explicitly written to do so. That
is the function object authors responsibility, not the default library
abstraction's.

(2) There is a misconception that we are wrapping a given instance of a
function or function object, which is not the case. We are encapsulating
a copy. Given that reference counting is used for one of two reasons --
optimisation or explicit sharing semantics -- visibly reference counting
something that is a copy rather than the original seems a little odd. It
is neither fish nor fowl: neither proper sharing semantics nor proper
copying semantics.

(3) The problem we are solving is precisely the one that you describe,
so let us look at it from the function object perspective. Imagine that
what I want is:

        class X
        {
        public:
                template<typename unary_function>
                virtual void f(unary_function) = 0;
                ...
        };

Clearly I can't have this, so the two forms of polymorphism --
parametric and inclusion -- are in tension. The resolution is to
detemplatise the pure virtual by allowing an adapter of some kind, say
unary_polyfunction (just to be neutral on names), that handles the
template->inheritance adaptation for us, retaining the semantics of the
desired design as much as possible:

        class X
        {
        public:
                virtual void f(unary_polyfunction<A, B>) = 0;
                ...
        };

This is exactly the kind of animal we are talking about. The idea of
throwing in reference counting messes this up: It is a change in the
original semantics outside the requirements of the design. This is about
polymorphism not about sharing. Sure, we can have sharing as a separate
feature -- another proxy or an adapted version, eg
shared_unary_polyfunction -- but we don't want to mess up the core
concept. If sharing were part of it, the first thing we'd need is an
unshare member function of some kind just so we could get back the
proper semantics! This is the kind of retrofit, interface-level hack we
should be avoiding.

In summary, including reference counting as part of the core concept is
undesirable:

(i) It combines two separate responsibilities into the same class,
disallowing their separate use. Because I obviously have not repeated it
enough, I will say it again: express independent ideas independently ;-)

(ii) It is inconsistent in that it is not like other uses of reference
counting for explicit sharing. These reference count an original object
known to the user, whereas the proposed reference counting
implementations count a copy generated by the implementation. So the
semantics are halfway between the full copying model and a proper
sharing implementation.

(iii) Much of the discussion of reference counting hinged around the
idea of optimisation. This proved to be a Red Herring as it was not
demonstrably an optimisation and, without changing to visible sharing
semantics, cannot be implemented practically. True optimisations based
on reference counting require either COW (which does not work well for
this case) or immutability (which is too restrictive).

Kevlin
____________________________________________________________

  Kevlin Henney phone: +44 117 942 2990
  Curbralan Limited mobile: +44 7801 073 508
  mailto:kevlin_at_[hidden] fax: +44 870 052 2289
  http://www.curbralan.com
____________________________________________________________


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