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