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