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