1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007 INRIA, Gustavo Carneiro
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
19  *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  */
21 #ifndef OBJECT_H
22 #define OBJECT_H
23 
24 #include <stdint.h>
25 #include <string>
26 #include <vector>
27 #include "ptr.h"
28 #include "attribute.h"
29 #include "object-base.h"
30 #include "attribute-construction-list.h"
31 #include "simple-ref-count.h"
32 
33 /**
34  * \file
35  * \ingroup object
36  * ns3::Object class declaration, which is the root of the Object hierarchy
37  * and Aggregation.
38  */
39 
40 namespace ns3 {
41 
42 class Object;
43 class AttributeAccessor;
44 class AttributeValue;
45 class TraceSourceAccessor;
46 
47 /**
48  * \ingroup core
49  * \defgroup object Object
50  * \brief Base classes which provide memory management and object aggregation.
51  */
52 
53 /**
54  * \ingroup object
55  * \ingroup ptr
56  * Standard Object deleter, used by SimpleRefCount
57  * to delete an Object when the reference count drops to zero.
58  */
59 struct ObjectDeleter
60 {
61   /**
62    * Smart pointer deleter implementation for Object.
63    *
64    * Delete implementation, forwards to the Object::DoDelete()
65    * method.
66    *
67    * \param [in] object The Object to delete.
68    */
69   inline static void Delete (Object *object);
70 };
71 
72 /**
73  * \ingroup object
74  * \brief A base class which provides memory management and object aggregation
75  *
76  * The memory management scheme is based on reference-counting with
77  * dispose-like functionality to break the reference cycles.
78  * The reference count is incremented and decremented with
79  * the methods Ref() and Unref(). If a reference cycle is
80  * present, the user is responsible for breaking it
81  * by calling Dispose() in a single location. This will
82  * eventually trigger the invocation of DoDispose() on itself and
83  * all its aggregates. The DoDispose() method is always automatically
84  * invoked from the Unref() method before destroying the Object,
85  * even if the user did not call Dispose() directly.
86  */
87 class Object : public SimpleRefCount<Object, ObjectBase, ObjectDeleter>
88 {
89 public:
90   /**
91    * \brief Register this type.
92    * \return The Object TypeId.
93    */
94   static TypeId GetTypeId (void);
95 
96   /**
97    * \brief Iterate over the Objects aggregated to an ns3::Object.
98    *
99    * This iterator does not allow you to iterate over the parent
100    * Object used to call Object::GetAggregateIterator.
101    *
102    * \note This is a java-style iterator.
103    */
104   class AggregateIterator
105   {
106   public:
107     /** Default constructor, which has no Object. */
108     AggregateIterator ();
109 
110     /**
111      * Check if there are more Aggregates to iterate over.
112      *
113      * \returns \c true if Next() can be called and return a non-null
114      *          pointer, \c false otherwise.
115      */
116     bool HasNext (void) const;
117 
118     /**
119      * Get the next Aggregated Object.
120      *
121      * \returns The next aggregated Object.
122      */
123     Ptr<const Object> Next (void);
124 
125   private:
126     /** Object needs access. */
127     friend class Object;
128     /**
129      * Construct from an Object.
130      *
131      * This is private, with Object as friend, so only Objects can create
132      * useful AggregateIterators.
133      *
134      * \param [in] object The Object whose Aggregates should be iterated over.
135      */
136     AggregateIterator (Ptr<const Object> object);
137     Ptr<const Object> m_object;                    //!< Parent Object.
138     uint32_t m_current;                            //!< Current position in parent's aggregates.
139   };
140 
141   /** Constructor. */
142   Object ();
143   /** Destructor. */
144   virtual ~Object ();
145 
146   virtual TypeId GetInstanceTypeId (void) const;
147 
148   /**
149    * Get a pointer to the requested aggregated Object.  If the type of object
150    * requested is ns3::Object, a Ptr to the calling object is returned.
151    *
152    * \tparam T \explicit The type of the aggregated Object to retrieve.
153    * \returns A pointer to the requested Object, or zero
154    *          if it could not be found.
155    */
156   template <typename T>
157   inline Ptr<T> GetObject (void) const;
158   /**
159    * Get a pointer to the requested aggregated Object by TypeId.  If the
160    * TypeId argument is ns3::Object, a Ptr to the calling object is returned.
161    *
162    * \tparam T \explicit The type of the aggregated Object to retrieve.
163    * \param [in] tid The TypeId of the requested Object.
164    * \returns A pointer to the requested Object with the specified TypeId,
165    *          or zero if it could not be found.
166    */
167   template <typename T>
168   Ptr<T> GetObject (TypeId tid) const;
169   /**
170    * Dispose of this Object.
171    *
172    * Run the DoDispose() methods of this Object and all the
173    * Objects aggregated to it.
174    * After calling this method, this Object is expected to be
175    * totally unusable except for the Ref() and Unref() methods.
176    *
177    * \note You can call Dispose() many times on the same Object or
178    * different Objects aggregated together, and DoDispose() will be
179    * called only once for each aggregated Object.
180    *
181    * This method is typically used to break reference cycles.
182    */
183   void Dispose (void);
184   /**
185    * Aggregate two Objects together.
186    *
187    * \param [in] other The other Object pointer
188    *
189    * This method aggregates the two Objects together: after this
190    * method returns, it becomes possible to call GetObject()
191    * on one to get the other, and vice-versa.
192    *
193    * This method calls the virtual method NotifyNewAggregates() to
194    * notify all aggregated Objects that they have been aggregated
195    * together.
196    *
197    * \sa NotifyNewAggregate()
198    */
199   void AggregateObject (Ptr<Object> other);
200 
201   /**
202    * Get an iterator to the Objects aggregated to this one.
203    *
204    * \returns An iterator to the first Object aggregated to this
205    *          Object.
206    *
207    * If no Objects are aggregated to this Object, then, the returned
208    * iterator will be empty and AggregateIterator::HasNext() will
209    * always return \c false.
210    */
211   AggregateIterator GetAggregateIterator (void) const;
212 
213   /**
214    * Invoke DoInitialize on all Objects aggregated to this one.
215    *
216    * This method calls the virtual DoInitialize() method on all the Objects
217    * aggregated to this Object. DoInitialize() will be called only once over
218    * the lifetime of an Object, just like DoDispose() is called only
219    * once.
220    *
221    * \sa DoInitialize()
222    */
223   void Initialize (void);
224 
225   /**
226    * Check if the object has been initialized.
227    *
228    * \brief Check if the object has been initialized.
229    * \returns \c true if the object has been initialized.
230    */
231   bool IsInitialized (void) const;
232 
233 protected:
234   /**
235    * Notify all Objects aggregated to this one of a new Object being
236    * aggregated.
237    *
238    * This method is invoked whenever two sets of Objects are aggregated
239    * together.  It is invoked exactly once for each Object in both sets.
240    * This method can be overridden by subclasses who wish to be notified
241    * of aggregation events. These subclasses must chain up to their
242    * base class NotifyNewAggregate() method.
243    *
244    * It is safe to call GetObject() and AggregateObject() from within
245    * this method.
246    */
247   virtual void NotifyNewAggregate (void);
248   /**
249    * Initialize() implementation.
250    *
251    * This method is called only once by Initialize(). If the user
252    * calls Initialize() multiple times, DoInitialize() is called only the
253    * first time.
254    *
255    * Subclasses are expected to override this method and chain up
256    * to their parent's implementation once they are done. It is
257    * safe to call GetObject() and AggregateObject() from within this method.
258    */
259   virtual void DoInitialize (void);
260   /**
261    * Destructor implementation.
262    *
263    * This method is called by Dispose() or by the Object's
264    * destructor, whichever comes first.
265    *
266    * Subclasses are expected to implement their real destruction
267    * code in an overridden version of this method and chain
268    * up to their parent's implementation once they are done.
269    * _i.e_, for simplicity, the destructor of every subclass should
270    * be empty and its content should be moved to the associated
271    * DoDispose() method.
272    *
273    * It is safe to call GetObject() from within this method.
274    */
275   virtual void DoDispose (void);
276   /**
277    * Copy an Object.
278    *
279    * \param [in] o the Object to copy.
280    *
281    * Allow subclasses to implement a copy constructor.
282    *
283    * While it is technically possible to implement a copy
284    * constructor in a subclass, we strongly discourage you
285    * from doing so. If you really want to do it anyway, you have
286    * to understand that this copy constructor will _not_
287    * copy aggregated Objects, _i.e_, if your Object instance
288    * is already aggregated to another Object and if you invoke
289    * this copy constructor, the new Object instance will be
290    * a pristine standalone Object instance not aggregated to
291    * any other Object. It is thus _your_ responsibility
292    * as a caller of this method to do what needs to be done
293    * (if it is needed) to ensure that the Object stays in a
294    * valid state.
295    */
296   Object (const Object &o);
297 
298 private:
299 
300   /**
301    * Copy an Object.
302    *
303    * \tparam T \deduced The type of the Object being copied.
304    * \param [in] object A pointer to the object to copy.
305    * \returns A copy of the input object.
306    *
307    * This method invoke the copy constructor of the input object
308    * and returns the new instance.
309    */
310   /**@{*/
311   template <typename T>
312   friend Ptr<T> CopyObject (Ptr<T> object);
313   template <typename T>
314   friend Ptr<T> CopyObject (Ptr<const T> object);
315   /**@}*/
316 
317   /**
318    * Set the TypeId and construct all Attributes of an Object.
319    *
320    * \tparam T \deduced The type of the Object to complete.
321    * \param [in] object The uninitialized object pointer.
322    * \return The derived object.
323    */
324   template <typename T>
325   friend Ptr<T> CompleteConstruct (T *object);
326 
327   /** Friends. @{*/
328   friend class ObjectFactory;
329   friend class AggregateIterator;
330   friend struct ObjectDeleter;
331   /**@}*/
332 
333   /**
334    * The list of Objects aggregated to this one.
335    *
336    * This data structure uses a classic C-style trick to
337    * hold an array of variable size without performing
338    * two memory allocations: the declaration of the structure
339    * declares a one-element array but when we allocate
340    * memory for this struct, we effectively allocate a larger
341    * chunk of memory than the struct to allow space for a larger
342    * variable sized buffer whose size is indicated by the element
343    * \c n
344    */
345   struct Aggregates
346   {
347     /** The number of entries in \c buffer. */
348     uint32_t n;
349     /** The array of Objects. */
350     Object *buffer[1];
351   };
352 
353   /**
354    * Find an Object of TypeId tid in the aggregates of this Object.
355    *
356    * \param [in] tid The TypeId we're looking for
357    * \return The matching Object, if it is found
358    */
359   Ptr<Object> DoGetObject (TypeId tid) const;
360   /**
361    * Verify that this Object is still live, by checking it's reference count.
362    * \return \c true if the reference count is non zero.
363    */
364   bool Check (void) const;
365   /**
366    * Check if any aggregated Objects have non-zero reference counts.
367    *
368    * \return \c true if any of our aggregates have non zero reference count.
369    *
370    * In some cases, when an event is scheduled against a subclass of
371    * Object, and if no one owns a reference directly to this Object, the
372    * Object is alive, has a refcount of zero and the method run when the
373    * event expires runs against the raw pointer, which means that we are
374    * manipulating an Object with a refcount of zero.  So, instead we
375    * check the aggregate reference count.
376    */
377   bool CheckLoose (void) const;
378   /**
379    * Set the TypeId of this Object.
380 
381    * \param [in] tid The TypeId value to set.
382    *
383    * Invoked from ns3::CreateObject only.
384    * Initialize the \c m_tid member variable to
385    * keep track of the type of this Object instance.
386    */
387   void SetTypeId (TypeId tid);
388   /**
389    * Initialize all member variables registered as Attributes of this TypeId.
390    *
391    * \param [in] attributes The attribute values used to initialize
392    *        the member variables of this Object's instance.
393    *
394    * Invoked from ns3::ObjectFactory::Create and ns3::CreateObject only.
395    * Initialize all the member variables which were
396    * registered with the associated TypeId.
397   */
398   void Construct (const AttributeConstructionList &attributes);
399 
400   /**
401    * Keep the list of aggregates in most-recently-used order
402    *
403    * \param [in,out] aggregates The list of aggregated Objects.
404    * \param [in] i The most recently used entry in the list.
405    */
406   void UpdateSortedArray (struct Aggregates *aggregates, uint32_t i) const;
407   /**
408    * Attempt to delete this Object.
409    *
410    * This method iterates over all aggregated Objects to check if they all
411    * have a zero refcount. If yes, the Object and all
412    * its aggregates are deleted. If not, nothing is done.
413    */
414   void DoDelete (void);
415 
416   /**
417    * Identifies the type of this Object instance.
418    */
419   TypeId m_tid;
420   /**
421    * Set to \c true when the DoDispose() method of the Object has run,
422    * \c false otherwise.
423    */
424   bool m_disposed;
425   /**
426    * Set to \c true once the DoInitialize() method has run,
427    * \c false otherwise
428    */
429   bool m_initialized;
430   /**
431    * A pointer to an array of 'aggregates'.
432    *
433    * A pointer to each Object aggregated to this Object is stored in this
434    * array.  The array is shared by all aggregated Objects
435    * so the size of the array is indirectly a reference count.
436    */
437   struct Aggregates * m_aggregates;
438   /**
439    * The number of times the Object was accessed with a
440    * call to GetObject().
441    *
442    * This integer is used to implement a heuristic to sort
443    * the array of aggregates in most-frequently accessed order.
444    */
445   uint32_t m_getObjectCount;
446 };
447 
448 template <typename T>
449 Ptr<T> CopyObject (Ptr<const T> object);
450 template <typename T>
451 Ptr<T> CopyObject (Ptr<T> object);
452 
453 } // namespace ns3
454 
455 namespace ns3 {
456 
457 
458 /*************************************************************************
459  *   The Object implementation which depends on templates
460  *************************************************************************/
461 
462 void
Delete(Object * object)463 ObjectDeleter::Delete (Object *object)
464 {
465   object->DoDelete ();
466 }
467 
468 template <typename T>
469 Ptr<T>
GetObject()470 Object::GetObject () const
471 {
472   // This is an optimization: if the cast works (which is likely),
473   // things will be pretty fast.
474   T *result = dynamic_cast<T *> (m_aggregates->buffer[0]);
475   if (result != 0)
476     {
477       return Ptr<T> (result);
478     }
479   // if the cast does not work, we try to do a full type check.
480   Ptr<Object> found = DoGetObject (T::GetTypeId ());
481   if (found != 0)
482     {
483       return Ptr<T> (static_cast<T *> (PeekPointer (found)));
484     }
485   return 0;
486 }
487 
488 /**
489  * Specialization of \link Object::GetObject () \endlink for
490  * objects of type ns3::Object.
491  *
492  * \returns A Ptr to the calling object.
493  */
494 template
495 <>
496 inline Ptr<Object>
GetObject()497 Object::GetObject () const
498 {
499   return Ptr<Object> (const_cast<Object *> (this));
500 }
501 
502 template <typename T>
503 Ptr<T>
GetObject(TypeId tid)504 Object::GetObject (TypeId tid) const
505 {
506   Ptr<Object> found = DoGetObject (tid);
507   if (found != 0)
508     {
509       return Ptr<T> (static_cast<T *> (PeekPointer (found)));
510     }
511   return 0;
512 }
513 
514 /**
515  * Specialization of \link Object::GetObject (TypeId tid) \endlink for
516  * objects of type ns3::Object.
517  *
518  * \param [in] tid The TypeId of the requested Object.
519  * \returns A Ptr to the calling object.
520  */
521 template
522 <>
523 inline Ptr<Object>
GetObject(TypeId tid)524 Object::GetObject (TypeId tid) const
525 {
526   if (tid == Object::GetTypeId ())
527     {
528       return Ptr<Object> (const_cast<Object *> (this));
529     }
530   else
531     {
532       return DoGetObject (tid);
533     }
534 }
535 
536 /*************************************************************************
537  *   The helper functions which need templates.
538  *************************************************************************/
539 
540 template <typename T>
CopyObject(Ptr<T> object)541 Ptr<T> CopyObject (Ptr<T> object)
542 {
543   Ptr<T> p = Ptr<T> (new T (*PeekPointer (object)), false);
544   NS_ASSERT (p->GetInstanceTypeId () == object->GetInstanceTypeId ());
545   return p;
546 }
547 
548 template <typename T>
CopyObject(Ptr<const T> object)549 Ptr<T> CopyObject (Ptr<const T> object)
550 {
551   Ptr<T> p = Ptr<T> (new T (*PeekPointer (object)), false);
552   NS_ASSERT (p->GetInstanceTypeId () == object->GetInstanceTypeId ());
553   return p;
554 }
555 
556 template <typename T>
CompleteConstruct(T * object)557 Ptr<T> CompleteConstruct (T *object)
558 {
559   object->SetTypeId (T::GetTypeId ());
560   object->Object::Construct (AttributeConstructionList ());
561   return Ptr<T> (object, false);
562 }
563 
564 /**
565  * \ingroup object
566  * @{
567  */
568 /**
569  * Create an object by type, with varying number of constructor parameters.
570  *
571  * \tparam T \explicit The type of the derived object to construct.
572  * \param [in] args Arguments to pass to the constructor.
573  * \return The derived object.
574  */
575 template <typename T, typename... Args>
CreateObject(Args &&...args)576 Ptr<T> CreateObject (Args&&... args)
577 {
578   return CompleteConstruct (new T (std::forward<Args> (args)...));
579 }
580 /**@}*/
581 
582 } // namespace ns3
583 
584 #endif /* OBJECT_H */
585 
586