ruby: message buffer: removes some unecessary functions.
[gem5.git] / src / base / refcnt.hh
index de589f7c5418ae690712e05e7ac9412668845c68..baf08c62e3461977d994f82aed9cc8d341cb467d 100644 (file)
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
  */
 
-#ifndef __REFCNT_HH__
-#define __REFCNT_HH__
+#ifndef __BASE_REFCNT_HH__
+#define __BASE_REFCNT_HH__
 
-#include <stddef.h> //For the NULL macro definition
+/**
+ * @file base/refcnt.hh
+ *
+ * Classes for managing reference counted objects.
+ */
 
+/**
+ * Derive from RefCounted if you want to enable reference counting of
+ * this class.  If you want to use automatic reference counting, you
+ * should use RefCountingPtr<T> instead of regular pointers.
+ */
 class RefCounted
 {
   private:
-    int count;
+    // The reference count is mutable because one may want to
+    // reference count a const pointer.  This really is OK because
+    // const is about logical constness of the object not really about
+    // strictly disallowing an object to change.
+    mutable int count;
 
   private:
+    // Don't allow a default copy constructor or copy operator on
+    // these objects because the default operation will copy the
+    // reference count as well and we certainly don't want that.
     RefCounted(const RefCounted &);
+    RefCounted &operator=(const RefCounted &);
 
   public:
+    /**
+     * We initialize the reference count to zero and the first object
+     * to take ownership of it must increment it to one.
+     *
+     * @attention A memory leak will occur if you never assign a newly
+     * constructed object to a reference counting pointer.
+     */
     RefCounted() : count(0) {}
+
+    /**
+     * We make the destructor virtual because we're likely to have
+     * virtual functions on reference counted objects.
+     *
+     * @todo Even if this were true, does it matter?  Shouldn't the
+     * derived class indicate this?  This only matters if we would
+     * ever choose to delete a "RefCounted *" which I doubt we'd ever
+     * do.  We don't ever delete a "void *".
+     */
     virtual ~RefCounted() {}
 
+    /// Increment the reference count
     void incref() { ++count; }
+
+    /// Decrement the reference count and destroy the object if all
+    /// references are gone.
     void decref() { if (--count <= 0) delete this; }
 };
 
+/**
+ * If you want a reference counting pointer to a mutable object,
+ * create it like this:
+ * @code
+ * typedef RefCountingPtr<Foo> FooPtr;
+ * @endcode
+ *
+ * @attention Do not use "const FooPtr"
+ * To create a reference counting pointer to a const object, use this:
+ * @code
+ * typedef RefCountingPtr<const Foo> ConstFooPtr;
+ * @endcode
+ *
+ * These two usages are analogous to iterator and const_iterator in the stl.
+ */
 template <class T>
 class RefCountingPtr
 {
   protected:
+    /// The stored pointer.
+    /// Arguably this should be private.
     T *data;
 
-    void copy(T *d)
+    /**
+     * Copy a new pointer value and increment the reference count if
+     * it is a valid pointer.  Note, this does not delete the
+     * reference any existing object.
+     * @param d Pointer to store.
+     */
+    void
+    copy(T *d)
     {
         data = d;
         if (data)
             data->incref();
     }
-    void del()
+
+    /**
+     * Delete the reference to any existing object if it is non NULL.
+     * @attention this doesn't clear the pointer value, so a double
+     * decref could happen if not careful.
+     */
+    void
+    del()
     {
         if (data)
             data->decref();
     }
-    void set(T *d)
-    {
-        if (data == d)
-            return;
 
-        del();
-        copy(d);
+    /**
+     * Drop the old reference and change it to something new.
+     */
+    void
+    set(T *d)
+    {
+        // Need to check if we're actually changing because otherwise
+        // we could delete the last reference before adding the new
+        // reference.
+        if (data != d) {
+            del();
+            copy(d);
+        }
     }
 
-
   public:
-    RefCountingPtr() : data(NULL) {}
+    /// Create an empty reference counting pointer.
+    RefCountingPtr() : data(0) {}
+
+    /// Create a new reference counting pointer to some object
+    /// (probably something newly created).  Adds a reference.
     RefCountingPtr(T *data) { copy(data); }
+
+    /// Create a new reference counting pointer by copying another
+    /// one.  Adds a reference.
     RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }
+
+    /// Destroy the pointer and any reference it may hold.
     ~RefCountingPtr() { del(); }
 
-    T *operator->() { return data; }
-    T &operator*() { return *data; }
-    T *get() { return data; }
+    // The following pointer access functions are const because they
+    // don't actually change the pointer, though the user could change
+    // what is pointed to.  This is analagous to a "Foo * const".
+
+    /// Access a member variable.
+    T *operator->() const { return data; }
+
+    /// Dereference the pointer.
+    T &operator*() const { return *data; }
 
-    const T *operator->() const { return data; }
-    const T &operator*() const { return *data; }
-    const T *get() const { return data; }
+    /// Directly access the pointer itself without taking a reference.
+    T *get() const { return data; }
 
-    RefCountingPtr &operator=(T *p) { set(p); return *this; }
-    RefCountingPtr &operator=(const RefCountingPtr &r)
+    /// Assign a new value to the pointer
+    const RefCountingPtr &operator=(T *p) { set(p); return *this; }
+
+    /// Copy the pointer from another RefCountingPtr
+    const RefCountingPtr &operator=(const RefCountingPtr &r)
     { return operator=(r.data); }
 
+    /// Check if the pointer is empty
     bool operator!() const { return data == 0; }
+
+    /// Check if the pointer is non-empty
     operator bool() const { return data != 0; }
 };
 
+/// Check for equality of two reference counting pointers.
 template<class T>
-bool operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
+inline bool operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
 { return l.get() == r.get(); }
 
+/// Check for equality of of a reference counting pointers and a
+/// regular pointer
 template<class T>
-bool operator==(const RefCountingPtr<T> &l, const T *r)
+inline bool operator==(const RefCountingPtr<T> &l, const T *r)
 { return l.get() == r; }
 
+/// Check for equality of of a reference counting pointers and a
+/// regular pointer
 template<class T>
-bool operator==(const T &l, const RefCountingPtr<T> &r)
+inline bool operator==(const T *l, const RefCountingPtr<T> &r)
 { return l == r.get(); }
 
+/// Check for inequality of two reference counting pointers.
 template<class T>
-bool operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
+inline bool operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
 { return l.get() != r.get(); }
 
+/// Check for inequality of of a reference counting pointers and a
+/// regular pointer
 template<class T>
-bool operator!=(const RefCountingPtr<T> &l, const T *r)
+inline bool operator!=(const RefCountingPtr<T> &l, const T *r)
 { return l.get() != r; }
 
+/// Check for inequality of of a reference counting pointers and a
+/// regular pointer
 template<class T>
-bool operator!=(const T &l, const RefCountingPtr<T> &r)
+inline bool operator!=(const T *l, const RefCountingPtr<T> &r)
 { return l != r.get(); }
 
-#endif // __REFCNT_HH__
+#endif // __BASE_REFCNT_HH__