<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
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>
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<> 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<MyConcrete> 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 <foo> 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 ->
+<verb>
+ void
+ SomeObject::someFunction() {
+ myConcretePointer->someOtherMethod();
+ }
+</verb>
+
+ <P>
+ When passing RefCount smart pointers, always pass them as their
+ native type, never as '*' or as '&'.
+
<!-- %%%% Chapter : CACHE MANAGER %%%% -->
<sect>Cache Manager