]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
document RefCount behaviour
authorrobertc <>
Tue, 17 Dec 2002 02:53:06 +0000 (02:53 +0000)
committerrobertc <>
Tue, 17 Dec 2002 02:53:06 +0000 (02:53 +0000)
doc/Programming-Guide/prog-guide.sgml

index dba8ba1fc38d1e62a9f707b6095cc30c4bee8cd7..72d73cf717a60a544118e12888220fa8b3923057 100644 (file)
@@ -2,7 +2,7 @@
 <article>
 <title>Squid Programmers Guide</title>
 <author>Squid Developers</author>
-<date>$Id: prog-guide.sgml,v 1.52 2002/09/15 05:41:27 robertc Exp $</date>
+<date>$Id: prog-guide.sgml,v 1.53 2002/12/16 19:53:06 robertc Exp $</date>
 
 <abstract>
 Squid is a WWW Cache application developed by the National Laboratory
@@ -319,6 +319,15 @@ Squid consists of the following major components
        provide a uniform method for managing callback data memory,
        canceling callbacks, and preventing erroneous memory accesses.
 
+<sect1>Refcount Data Allocator (C++ Only)
+
+       <P>
+       Manual reference counting such as cbdata uses is error prone,
+       and time consuming for the programmer. C++'s operator overloading
+       allows us to create automatic reference counting pointers, that will
+       free objects when they are no longer needed. With some care these 
+       objects can be passed to functions needed Callback Data pointers.
+
 <sect1>Debugging
 
        <P>
@@ -2975,6 +2984,158 @@ sub check {
        extern CBDATA_GLOBAL_TYPE(type_of_data);        /* CBDATA_UNDEF */
 </verb>
 
+<!-- %%%% Chapter : Reference Counting Data Allocator %%%% -->
+<sect>Refcount Data Allocator (C++ Only)
+
+       <P>
+       Manual reference counting such as cbdata uses is error prone,
+       and time consuming for the programmer. C++'s operator overloading
+       allows us to create automatic reference counting pointers, that will
+       free objects when they are no longer needed. With some care these 
+       objects can be passed to functions needed Callback Data pointers.
+
+<sect1> API
+
+       <P>
+       There are two classes involved in the automatic refcouting - a
+       'RefCountable' class that provides the mechanics for reference
+       counting a given derived class. And a 'RefCount' class that is the
+       smart pointer, and handles const correctness, and tells the RefCountable
+       class of references and dereferences.
+
+<sect2>        RefCountable
+
+       <P>
+       The RefCountable base class defines one abstract function -
+       <tt/deleteSelf()/. You must implement deleteSelf for each concrete
+       class and. deleteSelf() is a workaround for 'operator delete' not
+       being virtual. delete Self typically looks like:
+<verb>
+       void deleteSelf() const {delete this;}
+</verb>
+
+<sect2>        RefCount
+
+       <P>
+       The RefCount template class replaces pointers as parameters and 
+       variables of the class being reference counted. Typically one creates
+       a typedef to aid users.
+<verb>
+       class MyConcrete : public RefCountable {
+         public:
+           typedef RefCount<MyConcrete> Pointer;
+           void deleteSelf() const {delete this;}
+       };
+</verb>
+       Now, one can pass objects of MyConcrete::Pointer around.
+       
+<sect2>        CBDATA
+
+       <P>
+       To make a refcounting CBDATA class, you need to overload new and delete,
+       include a macro in your class definition, and ensure that some everyone
+       who would call you directly (not as a cbdata callback, but as a normal
+       use), holds a RefCount&lt;&gt; smart pointer to you.
+<verb>
+        class MyConcrete : public RefCountable {
+          public:
+            typedef RefCount<MyConcrete> Pointer;
+            void * operator new(size_t);
+            void operator delete (void *);
+            void deleteSelf() const {delete this;}
+          private:
+            CBDATA_CLASS(MyConcrete);
+        };
+          
+        ...
+        /* In your .cc file */
+        CBDATA_CLASS_INIT(MyConcrete);
+        
+        void *
+        MyConcrete::operator new (size_t)
+        {
+          CBDATA_INIT_TYPE(MyConcrete);
+          MyConcrete *result = cbdataAlloc(MyConcrete);
+          /* Mark result as being owned - we want the refcounter to do the
+           * delete call
+           */
+          cbdataReference(result);
+          return result;
+        }
+          
+        void
+        MyConcrete::operator delete (void *address)
+        {
+          MyConcrete *t = static_cast<MyConcrete *>(address);
+          cbdataFree(address);
+          /* And allow the memory to be freed */
+          cbdataReferenceDone (t);
+        }
+</verb>
+
+       When no RefCount&lt;MyConcrete&gt; smart pointers exist, the objects
+       delete method will be called. This will run the object destructor,
+       freeing any foreign resources it hold. Then cbdataFree
+       will be called, marking the object as invalid for all the cbdata 
+       functions that it may have queued. When they all return, the actual
+       memory will be returned to the pool.
+       
+<sect2> Using the Refcounter
+
+       <P>
+       Allocation and deallocation of refcounted objects (including those of
+       the RefCount template class) must be done via new() and delete(). If a
+       class that will hold an instance of a RefCount &lt;foo&gt; variable
+       does not use delete(), you must assign NULL to the variable before
+       it is freed. Failure to do this will result in memory leaks. You HAVE 
+       been warned.
+
+       <P>
+       Never call delete or deleteSelf on a RefCountable object. You will
+       create a large number of dangling references and squid will segfault
+       eventually.
+
+       <P>
+       Always create at least one RefCount smart pointer, so that the
+       reference counting mechanism will delete the object when it's not
+       needed.
+
+       <P>
+       Do not pass RefCount smart pointers outside the squid memory space.
+       They will invariably segfault when copied.
+
+       <P>
+       If, in a method, all other smart pointer holding objects may be deleted
+       or may set their smart pointers to NULL, then you will be deleted 
+       partway through the method (and thus crash). To prevent this, assign
+       a smart pointer to yourself:
+<verb>
+       void
+       MyConcrete::aMethod(){
+         /* This holds a reference to us */
+         Pointer aPointer(this);
+         /* This is a method that may mean we don't need to exist anymore */
+         someObject->someMethod();
+         /* This prevents aPointer being optimised away before this point,
+          * and must be the last line in our method 
+          */
+         aPointer = NULL;
+       }
+</verb>
+
+       <P>
+       Calling methods via smart pointers is easy just dereference via -&gt;
+<verb>
+       void
+       SomeObject::someFunction() {
+         myConcretePointer->someOtherMethod();
+       }
+</verb>
+       
+       <P>
+       When passing RefCount smart pointers, always pass them as their 
+       native type, never as '*' or as '&amp;'. 
+       
 <!-- %%%% Chapter : CACHE MANAGER %%%% -->
 <sect>Cache Manager