Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

Object.h

Go to the documentation of this file.
00001 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002 ///////////////////////////////////////////////////////////////////////////////
00003 //
00004 // Filename: Object.h (base)
00005 //
00006 // This file is a part of the UPPAAL toolkit.
00007 // Copyright (c) 1995 - 2000, Uppsala University and Aalborg University.
00008 // All right reserved.
00009 //
00010 // $Id: Object.h,v 1.6 2005/09/15 12:39:22 adavid Exp $
00011 //
00012 ///////////////////////////////////////////////////////////////////////////////
00013 
00014 #ifndef INCLUDE_BASE_OBJECT_H
00015 #define INCLUDE_BASE_OBJECT_H
00016 
00017 #include <stdlib.h>
00018 #include <assert.h>
00019 #include <iostream>
00020 
00021 namespace base
00022 {
00023     /** Base class to derive from if you want
00024      * to use Pointer<of something>. The reference
00025      * counting is done by Object.
00026      */
00027     class Object 
00028     {
00029     public:
00030         /** Constructor: initialize the reference counter.
00031          */
00032         Object() : refCounter(0) {}
00033 
00034         /** Destructor.
00035          */
00036         virtual ~Object() {}
00037         
00038         /** Add a reference to this object.
00039          * Use carefully because this will
00040          * affect deallocation.
00041          */
00042         void addReference()
00043         {
00044             ++refCounter;
00045         }
00046 
00047         /** Remove a reference to this object.
00048          * Use carefully because this will
00049          * affect deallocation.
00050          */
00051         void dropReference()
00052         {
00053             assert(refCounter > 0);
00054             if (--refCounter == 0) destroy();
00055         }
00056 
00057         /** This is useful to know if this object
00058          * may be modified safely.
00059          * @return true if there is only one reference
00060          * to this object.
00061          */
00062         bool isMutable() const
00063         {
00064             assert(refCounter > 0);
00065             return refCounter == 1;
00066         }
00067 
00068     protected:
00069 
00070         /** Wrapper to delete. It is virtual in
00071          * case we have objects that are not deallocated
00072          * by delete, in which case, the method is
00073          * overriden.
00074          */
00075         virtual void destroy()
00076         {
00077             assert(refCounter == 0);
00078             delete this;
00079         }
00080         
00081     private:
00082         unsigned int refCounter; /**< reference counter */
00083     };
00084 
00085 
00086     /** Pointer<of something> allows automatic
00087      * reference counting and automatic deallocation
00088      * when the reference drops to 0.
00089      * To use it, the referenced object must be
00090      * an Object.
00091      */
00092     template <class O>
00093     class Pointer 
00094     {
00095     public:
00096 
00097         /** Default constructor:
00098          * pointer to NULL
00099          */
00100         Pointer() : object(NULL) {}
00101 
00102         /** Copy constructor:
00103          * add reference
00104          * @param ptr: pointer to copy.
00105          */
00106         Pointer(const Pointer<O> &ptr)
00107             : object(ptr.object)
00108         {
00109             if (object) object->addReference();
00110         }
00111 
00112         /** Pointer constructor:
00113          * add reference
00114          * @param obj: pointed object
00115          */
00116         Pointer(O *obj)
00117             : object(obj)
00118         {
00119             if (object) object->addReference();
00120         }
00121 
00122         /** Destructor:
00123          * drop a reference
00124          */
00125         ~Pointer()
00126         {
00127             if (object) object->dropReference();
00128         }
00129 
00130         /** Dereference pointed object
00131          */
00132         O &operator *()  const { return *object; }
00133 
00134         /** Different wrappers to pointed object,
00135          * WITHOUT reference counting.
00136          */
00137         O *operator ->() const { return object; }
00138         operator O *()   const { return object; }
00139         O * getPtr()     const { return object; }
00140 
00141         /** @return true if pointer == NULL
00142          */
00143         bool null() const { return object == NULL; }
00144 
00145         /** @return true if pointer == NULL
00146          * This is a convenience operator to get
00147          * tests of the form if (!ptr) doThis();
00148          */
00149         bool operator !() const { return object == NULL; }
00150         
00151         /** Copy operator:
00152          * - add reference to new object
00153          * - drop reference to current object
00154          * - set new pointed object
00155          * Note: add 1st and then drop in case
00156          * it is an assignment a = a;
00157          */
00158         Pointer<O> &operator = (const Pointer<O> &ptr)
00159         {
00160             if (ptr.object) ptr.object->addReference();
00161             if (object) object->dropReference();
00162             object = ptr.object;
00163             return *this;
00164         }
00165 
00166         /** Cast operator. class To is the cast type.
00167          */
00168         template <class To>
00169         operator Pointer<To>() const
00170         {
00171             return Pointer<To>(static_cast<To*>(object));
00172         }
00173 
00174         /** Make sure this pointer is mutable.
00175          * The object class has to implement copy().
00176          */
00177         void setMutable()
00178         {
00179             if (object && !object->isMutable())
00180             {
00181                 object->dropReference();
00182                 object = object->copy();
00183                 object->addReference();
00184             }
00185         }
00186 
00187         /** Make sure the object is big enough.
00188          * The object type must have:
00189          * size_t size() const;      -> gives its current size.
00190          * static O* create(size_t); -> create a new object with given size.
00191          * O* copy(size_t) const;    -> create & copy (to smaller or larger).
00192          */
00193         void ensure(size_t newSize)
00194         {
00195             if (object)
00196             {
00197                 size_t size = object->size();
00198                 if (size < newSize)
00199                 {
00200                     size <<= 1;
00201                     O* larger = object->copy(size < newSize ? newSize : size);
00202                     object->dropReference();
00203                     object = larger;
00204                     object->addReference();
00205                 }
00206             }
00207             else
00208             {
00209                 object = O::create(newSize);
00210                 object->addReference();
00211             }
00212         }
00213             
00214     protected:
00215         ///< This is for child classes with special needs.
00216         void setPtr(O* obj) { object = obj; }
00217 
00218     private:
00219         O *object; /**< pointed object, must be an Object */
00220     };
00221 
00222     /** Simple overload of operator <<
00223      */
00224     template <class O> static inline
00225     std::ostream &operator << (std::ostream &out, const Pointer<O> &p)
00226     {
00227         return (p.null()) ? (out << "(NULL)") : (out << (*p));
00228     }
00229 
00230 } // namespace base
00231 
00232 #endif // INCLUDE_BASE_OBJECT_H

Generated on Fri Jun 30 00:02:30 2006 for Module base by  doxygen 1.4.2