Optimization: use a shared reference counter instead of a per-object counter in Object::Ref/Unref
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/core/object-ref-count.h Fri Nov 06 17:47:44 2009 +0100
1.3 @@ -0,0 +1,121 @@
1.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
1.5 +/*
1.6 + * Copyright (c) 2009 Mathieu Lacage
1.7 + *
1.8 + * This program is free software; you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License version 2 as
1.10 + * published by the Free Software Foundation;
1.11 + *
1.12 + * This program is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 + * GNU General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU General Public License
1.18 + * along with this program; if not, write to the Free Software
1.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.20 + *
1.21 + * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
1.22 + */
1.23 +#ifndef OBJECT_REF_COUNT_H
1.24 +#define OBJECT_REF_COUNT_H
1.25 +
1.26 +#include "empty.h"
1.27 +
1.28 +namespace ns3 {
1.29 +
1.30 +/**
1.31 + * This templated class provides the refcounting implementation
1.32 + * for the ns3::Object class.
1.33 + *
1.34 + * The tricky aspect of the implementation of this class is that
1.35 + * instead of storing a count directly, it keeps track of a pointer
1.36 + * to a count to allow multiple instances of the class to share the
1.37 + * same pointer/count. This is mainly used by the aggregation support
1.38 + * of the ns3::Object class
1.39 + */
1.40 +template <typename T, typename PARENT = empty>
1.41 +class ObjectRefCount : public PARENT
1.42 +{
1.43 +public:
1.44 + ObjectRefCount ()
1.45 + : m_count (new int (1))
1.46 + {}
1.47 + ObjectRefCount (const ObjectRefCount &o)
1.48 + : m_count (new int (1))
1.49 + {}
1.50 + ObjectRefCount & operator = (const ObjectRefCount &o)
1.51 + {
1.52 + *m_count = *o.m_count;
1.53 + return *this;
1.54 + }
1.55 + ~ObjectRefCount ()
1.56 + {
1.57 + m_count = 0;
1.58 + }
1.59 +
1.60 + /**
1.61 + * Get the reference count of the object. Normally not needed; for language bindings.
1.62 + */
1.63 + int GetReferenceCount (void) const {
1.64 + return *m_count;
1.65 + }
1.66 + /**
1.67 + * Increment the reference count. This method should not be called
1.68 + * by user code. Object instances are expected to be used in conjunction
1.69 + * of the Ptr template which would make calling Ref unecessary and
1.70 + * dangerous.
1.71 + */
1.72 + inline void Ref (void) const
1.73 + {
1.74 + (*m_count)++;
1.75 + }
1.76 + /**
1.77 + * Decrement the reference count. This method should not be called
1.78 + * by user code. Object instances are expected to be used in conjunction
1.79 + * of the Ptr template which would make calling Ref unecessary and
1.80 + * dangerous.
1.81 + */
1.82 + inline void Unref (void) const
1.83 + {
1.84 + (*m_count)--;
1.85 + if ((*m_count) == 0)
1.86 + {
1.87 + const_cast<ObjectRefCount<T,PARENT>*>(this)->DoDelete ();
1.88 + }
1.89 + }
1.90 +protected:
1.91 + /**
1.92 + * \param other another object
1.93 + *
1.94 + * This method makes this object and the input other object
1.95 + * share the same reference count.
1.96 + */
1.97 + void ShareCount (ObjectRefCount *other)
1.98 + {
1.99 + (*m_count) += (*other->m_count);
1.100 + delete other->m_count;
1.101 + other->m_count = m_count;
1.102 + }
1.103 + /**
1.104 + * Called just before deleting this object: when two
1.105 + * objects share the same reference count, the user
1.106 + * who is deleting them must be careful to delete the
1.107 + * associated count only once and this is done by calling
1.108 + * this method to get a reference to the count and, then,
1.109 + * calling delete on the count.
1.110 + *
1.111 + * \sa ns3::Object::DoDelete
1.112 + */
1.113 + int *PeekCountPtr (void) const
1.114 + {
1.115 + return m_count;
1.116 + }
1.117 +private:
1.118 + virtual void DoDelete (void) = 0;
1.119 + mutable int *m_count;
1.120 +};
1.121 +
1.122 +} // namespace ns3
1.123 +
1.124 +#endif /* OBJECT_REF_COUNT_H */
2.1 --- a/src/core/object.cc Fri Nov 06 11:27:17 2009 +0100
2.2 +++ b/src/core/object.cc Fri Nov 06 17:47:44 2009 +0100
2.3 @@ -79,8 +79,7 @@
2.4
2.5
2.6 Object::Object ()
2.7 - : m_count (1),
2.8 - m_tid (Object::GetTypeId ()),
2.9 + : m_tid (Object::GetTypeId ()),
2.10 m_disposed (false),
2.11 m_aggregates ((struct Aggregates *)malloc (sizeof (struct Aggregates))),
2.12 m_getObjectCount (0)
2.13 @@ -112,8 +111,7 @@
2.14 m_aggregates = 0;
2.15 }
2.16 Object::Object (const Object &o)
2.17 - : m_count (1),
2.18 - m_tid (o.m_tid),
2.19 + : m_tid (o.m_tid),
2.20 m_disposed (false),
2.21 m_aggregates ((struct Aggregates *)malloc (sizeof (struct Aggregates))),
2.22 m_getObjectCount (0)
2.23 @@ -121,11 +119,6 @@
2.24 m_aggregates->n = 1;
2.25 m_aggregates->buffer[0] = this;
2.26 }
2.27 -uint32_t
2.28 -Object::GetReferenceCount (void) const
2.29 -{
2.30 - return m_count;
2.31 -}
2.32 void
2.33 Object::Construct (const AttributeList &attributes)
2.34 {
2.35 @@ -231,6 +224,10 @@
2.36 Object *current = aggregates->buffer[i];
2.37 current->m_aggregates = aggregates;
2.38 }
2.39 +
2.40 + // share the counts
2.41 + ShareCount (other);
2.42 +
2.43 // Finally, call NotifyNewAggregate in the listed chain
2.44 for (uint32_t i = 0; i < n; i++)
2.45 {
2.46 @@ -271,7 +268,7 @@
2.47 bool
2.48 Object::Check (void) const
2.49 {
2.50 - return (m_count > 0);
2.51 + return (GetReferenceCount () > 0);
2.52 }
2.53
2.54 /* In some cases, when an event is scheduled against a subclass of
2.55 @@ -289,13 +286,12 @@
2.56 for (uint32_t i = 0; i < n; i++)
2.57 {
2.58 Object *current = m_aggregates->buffer[i];
2.59 - refcount += current->m_count;
2.60 + refcount += current->GetReferenceCount ();
2.61 }
2.62 return (refcount > 0);
2.63 }
2.64 -
2.65 void
2.66 -Object::MaybeDelete (void) const
2.67 +Object::DoDelete (void)
2.68 {
2.69 // First, check if any of the attached
2.70 // Object has a non-zero count.
2.71 @@ -303,7 +299,7 @@
2.72 for (uint32_t i = 0; i < n; i++)
2.73 {
2.74 Object *current = m_aggregates->buffer[i];
2.75 - if (current->m_count != 0)
2.76 + if (current->GetReferenceCount () != 0)
2.77 {
2.78 return;
2.79 }
2.80 @@ -319,6 +315,8 @@
2.81 }
2.82 }
2.83
2.84 + int *count = PeekCountPtr ();
2.85 +
2.86 // all attached objects have a zero count so,
2.87 // we can delete them all.
2.88 struct Aggregates *aggregates = m_aggregates;
2.89 @@ -331,6 +329,8 @@
2.90 Object *current = aggregates->buffer[0];
2.91 delete current;
2.92 }
2.93 +
2.94 + delete count;
2.95 }
2.96 } // namespace ns3
2.97
3.1 --- a/src/core/object.h Fri Nov 06 11:27:17 2009 +0100
3.2 +++ b/src/core/object.h Fri Nov 06 17:47:44 2009 +0100
3.3 @@ -28,6 +28,7 @@
3.4 #include "attribute.h"
3.5 #include "object-base.h"
3.6 #include "attribute-list.h"
3.7 +#include "object-ref-count.h"
3.8
3.9
3.10 namespace ns3 {
3.11 @@ -55,7 +56,7 @@
3.12 * invoked from the Object::Unref method before destroying the object, even if the user
3.13 * did not call Object::Dispose directly.
3.14 */
3.15 -class Object : public ObjectBase
3.16 +class Object : public ObjectRefCount<Object,ObjectBase>
3.17 {
3.18 public:
3.19 static TypeId GetTypeId (void);
3.20 @@ -99,26 +100,6 @@
3.21 virtual TypeId GetInstanceTypeId (void) const;
3.22
3.23 /**
3.24 - * Increment the reference count. This method should not be called
3.25 - * by user code. Object instances are expected to be used in conjunction
3.26 - * of the Ptr template which would make calling Ref unecessary and
3.27 - * dangerous.
3.28 - */
3.29 - inline void Ref (void) const;
3.30 - /**
3.31 - * Decrement the reference count. This method should not be called
3.32 - * by user code. Object instances are expected to be used in conjunction
3.33 - * of the Ptr template which would make calling Ref unecessary and
3.34 - * dangerous.
3.35 - */
3.36 - inline void Unref (void) const;
3.37 -
3.38 - /**
3.39 - * Get the reference count of the object. Normally not needed; for language bindings.
3.40 - */
3.41 - uint32_t GetReferenceCount (void) const;
3.42 -
3.43 - /**
3.44 * \returns a pointer to the requested interface or zero if it could not be found.
3.45 */
3.46 template <typename T>
3.47 @@ -234,13 +215,6 @@
3.48 bool Check (void) const;
3.49 bool CheckLoose (void) const;
3.50 /**
3.51 - * Attempt to delete this object. This method iterates
3.52 - * over all aggregated objects to check if they all
3.53 - * have a zero refcount. If yes, the object and all
3.54 - * its aggregates are deleted. If not, nothing is done.
3.55 - */
3.56 - void MaybeDelete (void) const;
3.57 - /**
3.58 * \param tid an TypeId
3.59 *
3.60 * Invoked from ns3::CreateObject only.
3.61 @@ -259,16 +233,15 @@
3.62 void Construct (const AttributeList &attributes);
3.63
3.64 void UpdateSortedArray (struct Aggregates *aggregates, uint32_t i) const;
3.65 + /**
3.66 + * Attempt to delete this object. This method iterates
3.67 + * over all aggregated objects to check if they all
3.68 + * have a zero refcount. If yes, the object and all
3.69 + * its aggregates are deleted. If not, nothing is done.
3.70 + */
3.71 + virtual void DoDelete (void);
3.72
3.73 /**
3.74 - * The reference count for this object. Each aggregate
3.75 - * has an individual reference count. When the global
3.76 - * reference count (the sum of all reference counts)
3.77 - * reaches zero, the object and all its aggregates is
3.78 - * deleted.
3.79 - */
3.80 - mutable uint32_t m_count;
3.81 - /**
3.82 * Identifies the type of this object instance.
3.83 */
3.84 TypeId m_tid;
3.85 @@ -363,22 +336,6 @@
3.86 * The Object implementation which depends on templates
3.87 *************************************************************************/
3.88
3.89 -void
3.90 -Object::Ref (void) const
3.91 -{
3.92 - m_count++;
3.93 -}
3.94 -void
3.95 -Object::Unref (void) const
3.96 -{
3.97 - NS_ASSERT (Check ());
3.98 - m_count--;
3.99 - if (m_count == 0)
3.100 - {
3.101 - MaybeDelete ();
3.102 - }
3.103 -}
3.104 -
3.105 template <typename T>
3.106 Ptr<T>
3.107 Object::GetObject () const
4.1 --- a/src/core/wscript Fri Nov 06 11:27:17 2009 +0100
4.2 +++ b/src/core/wscript Fri Nov 06 17:47:44 2009 +0100
4.3 @@ -126,6 +126,7 @@
4.4 'abort.h',
4.5 'names.h',
4.6 'vector.h',
4.7 + 'object-ref-count.h',
4.8 ]
4.9
4.10 if sys.platform == 'win32':