Boost logo

Boost :

From: Karl Nelson (kenelson_at_[hidden])
Date: 2000-11-22 16:57:24


With regard to the counting verses copy I see two faces which
really depend on the use.

For multicast with reverse dependencies counting is best because
copy would need to copy the dependencies. This makes copy
prohibitive in terms of run time. Further as this would need
to be a deep copy, abstraction of types is out, unless everything
had a clone procedure.

In the field of threading, cloning is clearly better. If you
had to reference count, then you would need to either place
locks in the library so that the references don't clobber each
other as the increment and decrement the counter. If you are also going to
do execution references so that if the object holding the callback
is destroyed while being called, then it is 4 "system calls" per
callback executed.

Ie. to handle this case

  class F
    {
      callback<void, int> r;
    };
  
  F* f;
  void foo(int)
    {
       ...
       delete f;
       ...
    }

  main() {
    f = new F;
    f->r=&foo;
    f->r(); // deletes f while r is being called thus
             // r is deleted, thus we risk trashing the stack unless
             // life of r is extended til last execution
  }

Means horribly slow code like

 class callback {
  R operator()(P1)
    { reference<callback> r(this);
      return impl(p1);
    }
  };

  class <class T>
  class reference
     {
       T* t_;
       reference(T* t) : t_(t)
         {
           mutexlock m(global_mutex);
           t->reference();
         }
       ~reference()
         {
           mutexlock m(global_mutex);
           t_->reference();
         }
     };
  class mutexlock {
     mutex& m_;
     mutexlock(mutex& m): m_(m)
       { m.lock(); }
     mutexlock()
       { m_.unlock(); }
   }

Or worse just to emit a function (while being exception safe).

Since strong safety with cheap copies (ref counted) is so
far from cheap thread calls (deep copy), clearly these need
to be distinct ideas. Trying to blend them will likely
compromise both.

(There are a load of other cases which involve multiple
threads which come to similar conclusions. Ref counting
across threads is slow.)

Considering the whole point of this exercise was to allow
threading, I think deep copy is likely the best route.
Remember a copy can be avoided with references in many cases,
while locking to protect shared internals in a threading
environment can not.

--Karl


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