mathieu@699
|
1 |
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
mathieu@699
|
2 |
/*
|
mathieu@699
|
3 |
* Copyright (c) 2007 INRIA, Gustavo Carneiro
|
mathieu@699
|
4 |
*
|
mathieu@699
|
5 |
* This program is free software; you can redistribute it and/or modify
|
mathieu@699
|
6 |
* it under the terms of the GNU General Public License version 2 as
|
mathieu@699
|
7 |
* published by the Free Software Foundation;
|
mathieu@699
|
8 |
*
|
mathieu@699
|
9 |
* This program is distributed in the hope that it will be useful,
|
mathieu@699
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mathieu@699
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mathieu@699
|
12 |
* GNU General Public License for more details.
|
mathieu@699
|
13 |
*
|
mathieu@699
|
14 |
* You should have received a copy of the GNU General Public License
|
mathieu@699
|
15 |
* along with this program; if not, write to the Free Software
|
mathieu@699
|
16 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
mathieu@699
|
17 |
*
|
mathieu@699
|
18 |
* Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
|
mathieu@699
|
19 |
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
mathieu@699
|
20 |
*/
|
mathieu@706
|
21 |
#ifndef OBJECT_H
|
mathieu@706
|
22 |
#define OBJECT_H
|
mathieu@699
|
23 |
|
mathieu@699
|
24 |
#include <stdint.h>
|
mathieu@699
|
25 |
#include <string>
|
mathieu@2542
|
26 |
#include <vector>
|
mathieu@699
|
27 |
#include "ptr.h"
|
mathieu@2438
|
28 |
#include "attribute.h"
|
mathieu@2372
|
29 |
#include "object-base.h"
|
mathieu@2633
|
30 |
#include "attribute-list.h"
|
mathieu@2246
|
31 |
|
mathieu@2246
|
32 |
|
mathieu@699
|
33 |
namespace ns3 {
|
mathieu@699
|
34 |
|
mathieu@2237
|
35 |
class Object;
|
mathieu@2436
|
36 |
class AttributeAccessor;
|
mathieu@2437
|
37 |
class AttributeValue;
|
mathieu@2459
|
38 |
class AttributeList;
|
mathieu@2463
|
39 |
class TraceSourceAccessor;
|
mathieu@1336
|
40 |
|
mathieu@718
|
41 |
/**
|
tomh@3182
|
42 |
* \ingroup core
|
tomh@3182
|
43 |
* \defgroup object Object
|
tomh@3182
|
44 |
*/
|
tomh@3182
|
45 |
/**
|
tomh@3182
|
46 |
* \ingroup object
|
mathieu@718
|
47 |
* \brief a base class which provides memory management and object aggregation
|
mathieu@718
|
48 |
*
|
mathieu@3190
|
49 |
* The memory management scheme is based on reference-counting with dispose-like
|
mathieu@3190
|
50 |
* functionality to break the reference cycles. The reference count is increamented
|
mathieu@3190
|
51 |
* and decremented with the methods Object::Ref and Object::Unref. If a reference cycle is
|
mathieu@3190
|
52 |
* present, the user is responsible for breaking it by calling Object::Dispose in
|
mathieu@3190
|
53 |
* a single location. This will eventually trigger the invocation of Object::DoDispose
|
mathieu@3190
|
54 |
* on itself and all its aggregates. The Object::DoDispose method is always automatically
|
mathieu@3190
|
55 |
* invoked from the Object::Unref method before destroying the object, even if the user
|
mathieu@3190
|
56 |
* did not call Object::Dispose directly.
|
mathieu@718
|
57 |
*/
|
mathieu@2370
|
58 |
class Object : public ObjectBase
|
mathieu@699
|
59 |
{
|
mathieu@699
|
60 |
public:
|
mathieu@2251
|
61 |
static TypeId GetTypeId (void);
|
mathieu@699
|
62 |
|
mathieu@2938
|
63 |
/**
|
mathieu@2938
|
64 |
* \brief Iterate over the objects aggregated to an ns3::Object.
|
mathieu@2938
|
65 |
*
|
mathieu@2938
|
66 |
* This iterator does not allow you to iterate over the initial
|
mathieu@2938
|
67 |
* object used to call Object::GetAggregateIterator.
|
mathieu@2938
|
68 |
*
|
mathieu@2938
|
69 |
* Note: this is a java-style iterator.
|
mathieu@2938
|
70 |
*/
|
mathieu@2937
|
71 |
class AggregateIterator
|
mathieu@2937
|
72 |
{
|
mathieu@2937
|
73 |
public:
|
mathieu@2937
|
74 |
AggregateIterator ();
|
mathieu@2937
|
75 |
|
mathieu@2938
|
76 |
/**
|
mathieu@2938
|
77 |
* \returns true if HasNext can be called and return a non-null
|
mathieu@2938
|
78 |
* pointer, false otherwise.
|
mathieu@2938
|
79 |
*/
|
mathieu@2937
|
80 |
bool HasNext (void) const;
|
mathieu@2938
|
81 |
|
mathieu@2938
|
82 |
/**
|
mathieu@2938
|
83 |
* \returns the next aggregated object.
|
mathieu@2938
|
84 |
*/
|
mathieu@2937
|
85 |
Ptr<const Object> Next (void);
|
mathieu@2937
|
86 |
private:
|
mathieu@2937
|
87 |
friend class Object;
|
mathieu@2937
|
88 |
AggregateIterator (Ptr<const Object> first);
|
mathieu@2937
|
89 |
Ptr<const Object> m_first;
|
mathieu@2937
|
90 |
Ptr<const Object> m_current;
|
mathieu@2937
|
91 |
};
|
mathieu@2937
|
92 |
|
mathieu@706
|
93 |
Object ();
|
mathieu@706
|
94 |
virtual ~Object ();
|
mathieu@2372
|
95 |
|
mathieu@2670
|
96 |
/*
|
mathieu@2670
|
97 |
* Implement the GetInstanceTypeId method defined in ObjectBase.
|
mathieu@2670
|
98 |
*/
|
mathieu@2634
|
99 |
virtual TypeId GetInstanceTypeId (void) const;
|
mathieu@2634
|
100 |
|
mathieu@2372
|
101 |
/**
|
mathieu@718
|
102 |
* Increment the reference count. This method should not be called
|
mathieu@718
|
103 |
* by user code. Object instances are expected to be used in conjunction
|
mathieu@718
|
104 |
* of the Ptr template which would make calling Ref unecessary and
|
mathieu@718
|
105 |
* dangerous.
|
mathieu@718
|
106 |
*/
|
mathieu@706
|
107 |
inline void Ref (void) const;
|
mathieu@718
|
108 |
/**
|
mathieu@718
|
109 |
* Decrement the reference count. This method should not be called
|
mathieu@718
|
110 |
* by user code. Object instances are expected to be used in conjunction
|
mathieu@718
|
111 |
* of the Ptr template which would make calling Ref unecessary and
|
mathieu@718
|
112 |
* dangerous.
|
mathieu@718
|
113 |
*/
|
mathieu@706
|
114 |
inline void Unref (void) const;
|
mathieu@718
|
115 |
/**
|
mathieu@718
|
116 |
* \returns a pointer to the requested interface or zero if it could not be found.
|
mathieu@2231
|
117 |
*/
|
mathieu@2231
|
118 |
template <typename T>
|
mathieu@2257
|
119 |
Ptr<T> GetObject (void) const;
|
mathieu@2231
|
120 |
/**
|
mathieu@2252
|
121 |
* \param tid the interface id of the requested interface
|
mathieu@2231
|
122 |
* \returns a pointer to the requested interface or zero if it could not be found.
|
mathieu@718
|
123 |
*/
|
mathieu@699
|
124 |
template <typename T>
|
mathieu@2257
|
125 |
Ptr<T> GetObject (TypeId tid) const;
|
mathieu@718
|
126 |
/**
|
mathieu@718
|
127 |
* Run the DoDispose methods of this object and all the
|
mathieu@718
|
128 |
* objects aggregated to it.
|
mathieu@718
|
129 |
* After calling this method, the object is expected to be
|
mathieu@718
|
130 |
* totally unusable except for the Ref and Unref methods.
|
mathieu@718
|
131 |
* It is an error to call Dispose twice on the same object
|
mathieu@2715
|
132 |
* instance.
|
mathieu@2715
|
133 |
*
|
mathieu@2715
|
134 |
* This method is typically used to break reference cycles.
|
mathieu@718
|
135 |
*/
|
mathieu@699
|
136 |
void Dispose (void);
|
mathieu@718
|
137 |
/**
|
mathieu@718
|
138 |
* \param other another object pointer
|
mathieu@718
|
139 |
*
|
mathieu@718
|
140 |
* This method aggregates the two objects together: after this
|
mathieu@2257
|
141 |
* method returns, it becomes possible to call GetObject
|
mathieu@718
|
142 |
* on one to get the other, and vice-versa.
|
mathieu@718
|
143 |
*/
|
mathieu@2258
|
144 |
void AggregateObject (Ptr<Object> other);
|
mathieu@1330
|
145 |
|
mathieu@2938
|
146 |
/**
|
mathieu@2938
|
147 |
* \returns an iterator to the first object aggregated to this
|
mathieu@2938
|
148 |
* object.
|
mathieu@2938
|
149 |
*
|
mathieu@2938
|
150 |
* If no objects are aggregated to this object, then, the returned
|
mathieu@2938
|
151 |
* iterator will be empty and AggregateIterator::HasNext will
|
mathieu@2938
|
152 |
* always return false.
|
mathieu@2938
|
153 |
*/
|
mathieu@2937
|
154 |
AggregateIterator GetAggregateIterator (void) const;
|
mathieu@2937
|
155 |
|
mathieu@699
|
156 |
protected:
|
mathieu@718
|
157 |
/**
|
mathieu@2715
|
158 |
* This method is called by Object::Dispose or by the object's
|
mathieu@2715
|
159 |
* destructor, whichever comes first.
|
mathieu@2715
|
160 |
*
|
mathieu@2715
|
161 |
* Subclasses are expected to implement their real destruction
|
mathieu@2715
|
162 |
* code in an overriden version of this method and chain
|
mathieu@2230
|
163 |
* up to their parent's implementation once they are done.
|
mathieu@2715
|
164 |
* i.e., for simplicity, the destructor of every subclass should
|
mathieu@2715
|
165 |
* be empty and its content should be moved to the associated
|
mathieu@2715
|
166 |
* DoDispose method.
|
mathieu@2230
|
167 |
*/
|
mathieu@2230
|
168 |
virtual void DoDispose (void);
|
mathieu@2667
|
169 |
/**
|
mathieu@2667
|
170 |
* \param o the object to copy.
|
mathieu@2667
|
171 |
*
|
mathieu@2667
|
172 |
* Allow subclasses to implement a copy constructor.
|
mathieu@2667
|
173 |
* While it is technically possible to implement a copy
|
mathieu@2667
|
174 |
* constructor in a subclass, we strongly discourage you
|
mathieu@2667
|
175 |
* to do so. If you really want to do it anyway, you have
|
mathieu@2667
|
176 |
* to understand that this copy constructor will _not_
|
mathieu@2667
|
177 |
* copy aggregated objects. i.e., if your object instance
|
mathieu@2667
|
178 |
* is already aggregated to another object and if you invoke
|
mathieu@2667
|
179 |
* this copy constructor, the new object instance will be
|
mathieu@2667
|
180 |
* a pristine standlone object instance not aggregated to
|
mathieu@2667
|
181 |
* any other object. It is thus _your_ responsability
|
mathieu@2667
|
182 |
* as a caller of this method to do what needs to be done
|
mathieu@2667
|
183 |
* (if it is needed) to ensure that the object stays in a
|
mathieu@2667
|
184 |
* valid state.
|
mathieu@2667
|
185 |
*/
|
mathieu@2667
|
186 |
Object (const Object &o);
|
mathieu@2230
|
187 |
private:
|
mathieu@2667
|
188 |
|
mathieu@2372
|
189 |
template <typename T>
|
mathieu@2459
|
190 |
friend Ptr<T> CreateObject (const AttributeList &attributes);
|
mathieu@2607
|
191 |
template <typename T>
|
mathieu@2607
|
192 |
friend Ptr<T> CopyObject (Ptr<T> object);
|
mathieu@2924
|
193 |
template <typename T>
|
mathieu@2924
|
194 |
friend Ptr<T> CopyObject (Ptr<const T> object);
|
mathieu@2372
|
195 |
|
mathieu@2631
|
196 |
friend class ObjectFactory;
|
mathieu@2937
|
197 |
friend class AggregateIterator;
|
mathieu@2631
|
198 |
|
mathieu@2257
|
199 |
Ptr<Object> DoGetObject (TypeId tid) const;
|
mathieu@2230
|
200 |
bool Check (void) const;
|
mathieu@2230
|
201 |
bool CheckLoose (void) const;
|
mathieu@2372
|
202 |
/**
|
mathieu@2372
|
203 |
* Attempt to delete this object. This method iterates
|
mathieu@2372
|
204 |
* over all aggregated objects to check if they all
|
mathieu@2372
|
205 |
* have a zero refcount. If yes, the object and all
|
mathieu@2372
|
206 |
* its aggregates are deleted. If not, nothing is done.
|
mathieu@2372
|
207 |
*/
|
mathieu@2230
|
208 |
void MaybeDelete (void) const;
|
mathieu@2230
|
209 |
/**
|
mathieu@2252
|
210 |
* \param tid an TypeId
|
mathieu@718
|
211 |
*
|
mathieu@2372
|
212 |
* Invoked from ns3::CreateObject only.
|
mathieu@2372
|
213 |
* Initialize the m_tid member variable to
|
mathieu@2372
|
214 |
* keep track of the type of this object instance.
|
mathieu@718
|
215 |
*/
|
mathieu@2252
|
216 |
void SetTypeId (TypeId tid);
|
mathieu@2637
|
217 |
/**
|
mathieu@2458
|
218 |
* \param attributes the attribute values used to initialize
|
mathieu@2372
|
219 |
* the member variables of this object's instance.
|
mathieu@2372
|
220 |
*
|
mathieu@2637
|
221 |
* Invoked from ns3::ObjectFactory::Create and ns3::CreateObject only.
|
mathieu@2372
|
222 |
* Initialize all the member variables which were
|
mathieu@2372
|
223 |
* registered with the associated TypeId.
|
mathieu@2372
|
224 |
*/
|
mathieu@2459
|
225 |
void Construct (const AttributeList &attributes);
|
mathieu@2230
|
226 |
|
mathieu@2372
|
227 |
/**
|
mathieu@2372
|
228 |
* The reference count for this object. Each aggregate
|
mathieu@2372
|
229 |
* has an individual reference count. When the global
|
mathieu@2372
|
230 |
* reference count (the sum of all reference counts)
|
mathieu@2372
|
231 |
* reaches zero, the object and all its aggregates is
|
mathieu@2372
|
232 |
* deleted.
|
mathieu@2372
|
233 |
*/
|
mathieu@706
|
234 |
mutable uint32_t m_count;
|
mathieu@2372
|
235 |
/**
|
mathieu@2372
|
236 |
* Identifies the type of this object instance.
|
mathieu@2372
|
237 |
*/
|
mathieu@2252
|
238 |
TypeId m_tid;
|
mathieu@2372
|
239 |
/**
|
mathieu@2372
|
240 |
* Set to true when the DoDispose method of the object
|
mathieu@2372
|
241 |
* has run, false otherwise.
|
mathieu@2372
|
242 |
*/
|
mathieu@713
|
243 |
bool m_disposed;
|
mathieu@2372
|
244 |
/**
|
mathieu@2372
|
245 |
* A pointer to the next aggregate object. This is a circular
|
mathieu@2372
|
246 |
* linked list of aggregated objects: the last one points
|
mathieu@2372
|
247 |
* back to the first one. If an object is not aggregated to
|
mathieu@2372
|
248 |
* any other object, the value of this field is equal to the
|
mathieu@2372
|
249 |
* value of the 'this' pointer.
|
mathieu@2372
|
250 |
*/
|
mathieu@706
|
251 |
Object *m_next;
|
mathieu@699
|
252 |
};
|
mathieu@699
|
253 |
|
mathieu@2670
|
254 |
/**
|
mathieu@2688
|
255 |
* \param object a pointer to the object to copy.
|
mathieu@2670
|
256 |
* \returns a copy of the input object.
|
mathieu@2670
|
257 |
*
|
mathieu@2670
|
258 |
* This method invoke the copy constructor of the input object
|
mathieu@2670
|
259 |
* and returns the new instance.
|
mathieu@2670
|
260 |
*/
|
mathieu@2667
|
261 |
template <typename T>
|
mathieu@2924
|
262 |
Ptr<T> CopyObject (Ptr<const T> object);
|
mathieu@2924
|
263 |
template <typename T>
|
mathieu@2688
|
264 |
Ptr<T> CopyObject (Ptr<T> object);
|
mathieu@2667
|
265 |
|
mathieu@2924
|
266 |
|
mathieu@2670
|
267 |
/**
|
mathieu@2670
|
268 |
* \param attributes a list of attributes to set on the
|
mathieu@2670
|
269 |
* object during construction.
|
mathieu@2670
|
270 |
* \returns a pointer to a newly allocated object.
|
mathieu@2670
|
271 |
*
|
mathieu@2670
|
272 |
* This allocates an object on the heap and initializes
|
mathieu@2670
|
273 |
* it with a set of attributes.
|
mathieu@2670
|
274 |
*/
|
mathieu@2667
|
275 |
template <typename T>
|
mathieu@2667
|
276 |
Ptr<T> CreateObject (const AttributeList &attributes);
|
mathieu@2667
|
277 |
|
mathieu@2670
|
278 |
/**
|
mathieu@2670
|
279 |
* \param n1 name of attribute
|
mathieu@2670
|
280 |
* \param v1 value of attribute
|
mathieu@2670
|
281 |
* \param n2 name of attribute
|
mathieu@2670
|
282 |
* \param v2 value of attribute
|
mathieu@2670
|
283 |
* \param n3 name of attribute
|
mathieu@2670
|
284 |
* \param v3 value of attribute
|
mathieu@2670
|
285 |
* \param n4 name of attribute
|
mathieu@2670
|
286 |
* \param v4 value of attribute
|
mathieu@2670
|
287 |
* \param n5 name of attribute
|
mathieu@2670
|
288 |
* \param v5 value of attribute
|
mathieu@2670
|
289 |
* \param n6 name of attribute
|
mathieu@2670
|
290 |
* \param v6 value of attribute
|
mathieu@2670
|
291 |
* \param n7 name of attribute
|
mathieu@2670
|
292 |
* \param v7 value of attribute
|
mathieu@2670
|
293 |
* \param n8 name of attribute
|
mathieu@2670
|
294 |
* \param v8 value of attribute
|
mathieu@2670
|
295 |
* \param n9 name of attribute
|
mathieu@2670
|
296 |
* \param v9 value of attribute
|
mathieu@2670
|
297 |
* \returns a pointer to a newly allocated object.
|
mathieu@2670
|
298 |
*
|
mathieu@2670
|
299 |
* This allocates an object on the heap and initializes
|
mathieu@2670
|
300 |
* it with a set of attributes.
|
mathieu@2670
|
301 |
*/
|
mathieu@2667
|
302 |
template <typename T>
|
mathieu@2667
|
303 |
Ptr<T>
|
mathieu@2965
|
304 |
CreateObject (std::string n1 = "", const AttributeValue & v1 = EmptyAttributeValue (),
|
mathieu@2965
|
305 |
std::string n2 = "", const AttributeValue & v2 = EmptyAttributeValue (),
|
mathieu@2965
|
306 |
std::string n3 = "", const AttributeValue & v3 = EmptyAttributeValue (),
|
mathieu@2965
|
307 |
std::string n4 = "", const AttributeValue & v4 = EmptyAttributeValue (),
|
mathieu@2965
|
308 |
std::string n5 = "", const AttributeValue & v5 = EmptyAttributeValue (),
|
mathieu@2965
|
309 |
std::string n6 = "", const AttributeValue & v6 = EmptyAttributeValue (),
|
mathieu@2965
|
310 |
std::string n7 = "", const AttributeValue & v7 = EmptyAttributeValue (),
|
mathieu@2965
|
311 |
std::string n8 = "", const AttributeValue & v8 = EmptyAttributeValue (),
|
mathieu@2965
|
312 |
std::string n9 = "", const AttributeValue & v9 = EmptyAttributeValue ());
|
mathieu@2667
|
313 |
|
mathieu@2667
|
314 |
|
mathieu@2667
|
315 |
|
mathieu@699
|
316 |
} // namespace ns3
|
mathieu@699
|
317 |
|
mathieu@699
|
318 |
namespace ns3 {
|
mathieu@699
|
319 |
|
mathieu@2372
|
320 |
/*************************************************************************
|
mathieu@2372
|
321 |
* The Object implementation which depends on templates
|
mathieu@2372
|
322 |
*************************************************************************/
|
mathieu@2237
|
323 |
|
mathieu@701
|
324 |
void
|
mathieu@706
|
325 |
Object::Ref (void) const
|
mathieu@701
|
326 |
{
|
mathieu@701
|
327 |
m_count++;
|
mathieu@701
|
328 |
}
|
mathieu@701
|
329 |
void
|
mathieu@706
|
330 |
Object::Unref (void) const
|
mathieu@701
|
331 |
{
|
mathieu@701
|
332 |
NS_ASSERT (Check ());
|
mathieu@701
|
333 |
m_count--;
|
mathieu@701
|
334 |
if (m_count == 0)
|
mathieu@701
|
335 |
{
|
mathieu@701
|
336 |
MaybeDelete ();
|
mathieu@701
|
337 |
}
|
mathieu@701
|
338 |
}
|
mathieu@701
|
339 |
|
mathieu@699
|
340 |
template <typename T>
|
mathieu@699
|
341 |
Ptr<T>
|
mathieu@2257
|
342 |
Object::GetObject () const
|
mathieu@2231
|
343 |
{
|
mathieu@2257
|
344 |
Ptr<Object> found = DoGetObject (T::GetTypeId ());
|
mathieu@2231
|
345 |
if (found != 0)
|
mathieu@2231
|
346 |
{
|
mathieu@2231
|
347 |
return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
|
mathieu@2231
|
348 |
}
|
mathieu@2231
|
349 |
return 0;
|
mathieu@2231
|
350 |
}
|
mathieu@2231
|
351 |
|
mathieu@2231
|
352 |
template <typename T>
|
mathieu@2231
|
353 |
Ptr<T>
|
mathieu@2257
|
354 |
Object::GetObject (TypeId tid) const
|
mathieu@699
|
355 |
{
|
mathieu@2257
|
356 |
Ptr<Object> found = DoGetObject (tid);
|
mathieu@699
|
357 |
if (found != 0)
|
mathieu@699
|
358 |
{
|
mathieu@699
|
359 |
return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
|
mathieu@699
|
360 |
}
|
mathieu@699
|
361 |
return 0;
|
mathieu@699
|
362 |
}
|
mathieu@699
|
363 |
|
mathieu@2372
|
364 |
/*************************************************************************
|
mathieu@2372
|
365 |
* The helper functions which need templates.
|
mathieu@2372
|
366 |
*************************************************************************/
|
mathieu@2372
|
367 |
|
mathieu@2607
|
368 |
template <typename T>
|
mathieu@2688
|
369 |
Ptr<T> CopyObject (Ptr<T> object)
|
mathieu@2607
|
370 |
{
|
mathieu@2690
|
371 |
Ptr<T> p = Ptr<T> (new T (*PeekPointer (object)), false);
|
mathieu@2690
|
372 |
NS_ASSERT (p->m_tid == object->m_tid);
|
mathieu@2607
|
373 |
return p;
|
mathieu@2607
|
374 |
}
|
mathieu@2607
|
375 |
|
mathieu@2924
|
376 |
template <typename T>
|
mathieu@2924
|
377 |
Ptr<T> CopyObject (Ptr<const T> object)
|
mathieu@2924
|
378 |
{
|
mathieu@2924
|
379 |
Ptr<T> p = Ptr<T> (new T (*PeekPointer (object)), false);
|
mathieu@2924
|
380 |
NS_ASSERT (p->m_tid == object->m_tid);
|
mathieu@2924
|
381 |
return p;
|
mathieu@2924
|
382 |
}
|
mathieu@2924
|
383 |
|
mathieu@2372
|
384 |
|
mathieu@2372
|
385 |
template <typename T>
|
mathieu@2459
|
386 |
Ptr<T> CreateObject (const AttributeList &attributes)
|
mathieu@2372
|
387 |
{
|
mathieu@2372
|
388 |
Ptr<T> p = Ptr<T> (new T (), false);
|
mathieu@2372
|
389 |
p->SetTypeId (T::GetTypeId ());
|
mathieu@2458
|
390 |
p->Object::Construct (attributes);
|
mathieu@2372
|
391 |
return p;
|
mathieu@2372
|
392 |
}
|
mathieu@2372
|
393 |
|
mathieu@2230
|
394 |
template <typename T>
|
mathieu@2372
|
395 |
Ptr<T>
|
mathieu@2965
|
396 |
CreateObject (std::string n1 = "", const AttributeValue & v1 = EmptyAttributeValue (),
|
mathieu@2965
|
397 |
std::string n2 = "", const AttributeValue & v2 = EmptyAttributeValue (),
|
mathieu@2965
|
398 |
std::string n3 = "", const AttributeValue & v3 = EmptyAttributeValue (),
|
mathieu@2965
|
399 |
std::string n4 = "", const AttributeValue & v4 = EmptyAttributeValue (),
|
mathieu@2965
|
400 |
std::string n5 = "", const AttributeValue & v5 = EmptyAttributeValue (),
|
mathieu@2965
|
401 |
std::string n6 = "", const AttributeValue & v6 = EmptyAttributeValue (),
|
mathieu@2965
|
402 |
std::string n7 = "", const AttributeValue & v7 = EmptyAttributeValue (),
|
mathieu@2965
|
403 |
std::string n8 = "", const AttributeValue & v8 = EmptyAttributeValue (),
|
mathieu@2965
|
404 |
std::string n9 = "", const AttributeValue & v9 = EmptyAttributeValue ())
|
mathieu@2372
|
405 |
{
|
mathieu@2459
|
406 |
AttributeList attributes;
|
mathieu@2591
|
407 |
if (n1 == "")
|
mathieu@2591
|
408 |
{
|
mathieu@2591
|
409 |
goto end;
|
mathieu@2591
|
410 |
}
|
mathieu@2458
|
411 |
attributes.SetWithTid (T::GetTypeId (), n1, v1);
|
mathieu@2591
|
412 |
if (n2 == "")
|
mathieu@2591
|
413 |
{
|
mathieu@2591
|
414 |
goto end;
|
mathieu@2591
|
415 |
}
|
mathieu@2458
|
416 |
attributes.SetWithTid (T::GetTypeId (), n2, v2);
|
mathieu@2591
|
417 |
if (n3 == "")
|
mathieu@2591
|
418 |
{
|
mathieu@2591
|
419 |
goto end;
|
mathieu@2591
|
420 |
}
|
mathieu@2489
|
421 |
attributes.SetWithTid (T::GetTypeId (), n3, v3);
|
mathieu@2591
|
422 |
if (n4 == "")
|
mathieu@2591
|
423 |
{
|
mathieu@2591
|
424 |
goto end;
|
mathieu@2591
|
425 |
}
|
mathieu@2489
|
426 |
attributes.SetWithTid (T::GetTypeId (), n4, v4);
|
mathieu@2591
|
427 |
if (n5 == "")
|
mathieu@2591
|
428 |
{
|
mathieu@2591
|
429 |
goto end;
|
mathieu@2591
|
430 |
}
|
mathieu@2489
|
431 |
attributes.SetWithTid (T::GetTypeId (), n5, v5);
|
mathieu@2591
|
432 |
if (n6 == "")
|
mathieu@2591
|
433 |
{
|
mathieu@2591
|
434 |
goto end;
|
mathieu@2591
|
435 |
}
|
mathieu@2489
|
436 |
attributes.SetWithTid (T::GetTypeId (), n6, v6);
|
mathieu@2591
|
437 |
if (n7 == "")
|
mathieu@2591
|
438 |
{
|
mathieu@2591
|
439 |
goto end;
|
mathieu@2591
|
440 |
}
|
mathieu@2489
|
441 |
attributes.SetWithTid (T::GetTypeId (), n7, v7);
|
mathieu@2591
|
442 |
if (n8 == "")
|
mathieu@2591
|
443 |
{
|
mathieu@2591
|
444 |
goto end;
|
mathieu@2591
|
445 |
}
|
mathieu@2489
|
446 |
attributes.SetWithTid (T::GetTypeId (), n8, v8);
|
mathieu@2591
|
447 |
if (n9 == "")
|
mathieu@2591
|
448 |
{
|
mathieu@2591
|
449 |
goto end;
|
mathieu@2591
|
450 |
}
|
mathieu@2489
|
451 |
attributes.SetWithTid (T::GetTypeId (), n9, v9);
|
mathieu@2591
|
452 |
end:
|
mathieu@2458
|
453 |
return CreateObject<T> (attributes);
|
mathieu@2372
|
454 |
}
|
mathieu@2372
|
455 |
|
mathieu@699
|
456 |
} // namespace ns3
|
mathieu@699
|
457 |
|
mathieu@706
|
458 |
#endif /* OBJECT_H */
|
mathieu@699
|
459 |
|