A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
object-base.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8#include "object-base.h"
9
10#include "abort.h"
13#include "fatal-error.h"
14#include "log.h"
15#include "string.h"
17
18/**
19 * @file
20 * @ingroup object
21 * ns3::ObjectBase class implementation.
22 */
23
24namespace ns3
25{
26// Explicit instantiation declaration
27
28/**
29 * @ingroup callback
30 * Explicit instantiation for ObjectBase
31 * @return A wrapper Callback
32 * \sa ns3::MakeCallback
33 */
36template class CallbackImpl<ObjectBase*>;
37
38NS_LOG_COMPONENT_DEFINE("ObjectBase");
39
41
42/**
43 * Ensure the TypeId for ObjectBase gets fully configured
44 * to anchor the inheritance tree properly.
45 *
46 * @relates ns3::ObjectBase
47 *
48 * @return The TypeId for ObjectBase.
49 */
50static TypeId
52{
54 TypeId tid = TypeId("ns3::ObjectBase");
55 tid.SetParent(tid);
56 tid.SetGroupName("Core");
57 return tid;
58}
59
62{
64 static TypeId tid = GetObjectIid();
65 return tid;
66}
67
72
73void
78
79void
81{
82 // loop over the inheritance tree back to the Object base class.
83 NS_LOG_FUNCTION(this << &attributes);
85 TypeId objectTid;
86 // the TypeId of a class derived from Object is initialized to "ns3::Object"; for a class
87 // deriving from Object, check that this function is called after that the correct TypeId is set
88 // to ensure that the attributes of the class are initialized
89 NS_ABORT_MSG_IF(TypeId::LookupByNameFailSafe("ns3::Object", &objectTid) && tid == objectTid,
90 "ObjectBase::ConstructSelf() has been called on an object of a class derived "
91 "from the Object class, but the TypeId is still set to ns3::Object.\n"
92 "This is known to happen in two cases:\n"
93 "- ObjectBase::ConstructSelf() is called in the class constructor; in this "
94 "case, override ObjectBase::NotifyConstructionCompleted() to access the "
95 "initial values of the object attributes as soon as object construction is "
96 "completed (see issue #1249)\n"
97 "- the class deriving from Object does not define a static GetTypeId() method");
98 do // Do this tid and all parents
99 {
100 // loop over all attributes in object type
101 NS_LOG_DEBUG("construct tid=" << tid.GetName() << ", params=" << tid.GetAttributeN());
102 for (uint32_t i = 0; i < tid.GetAttributeN(); i++)
103 {
105 NS_LOG_DEBUG("try to construct \"" << tid.GetName() << "::" << info.name << "\"");
106 // is this attribute stored in this AttributeConstructionList instance ?
107 Ptr<const AttributeValue> value = attributes.Find(info.checker);
108 std::string where = "argument";
109
110 // See if this attribute should not be set here in the
111 // constructor.
112 if (!(info.flags & TypeId::ATTR_CONSTRUCT))
113 {
114 // Handle this attribute if it should not be
115 // set here.
116 if (!value)
117 {
118 // Skip this attribute if it's not in the
119 // AttributeConstructionList.
120 NS_LOG_DEBUG("skipping, not settable at construction");
121 continue;
122 }
123 else
124 {
125 // This is an error because this attribute is not
126 // settable in its constructor but is present in
127 // the AttributeConstructionList.
128 NS_FATAL_ERROR("Attribute name="
129 << info.name << " tid=" << tid.GetName()
130 << ": initial value cannot be set using attributes");
131 }
132 }
133
134 if (!value)
135 {
136 NS_LOG_DEBUG("trying to set from environment variable NS_ATTRIBUTE_DEFAULT");
137 auto [found, val] =
138 EnvironmentVariable::Get("NS_ATTRIBUTE_DEFAULT", tid.GetAttributeFullName(i));
139 if (found)
140 {
141 NS_LOG_DEBUG("found in environment: " << val);
142 value = Create<StringValue>(val);
143 where = "env var";
144 }
145 }
146
147 bool initial{false};
148 if (!value)
149 {
150 // This is guaranteed to exist
151 NS_LOG_DEBUG("falling back to initial value from tid");
152 value = info.initialValue;
153 where = "initial value";
154 initial = true;
155 }
156
157 // We have a matching attribute value, if only from the initialValue
158 if (DoSet(info.accessor, info.checker, *value) || initial)
159 {
160 // Setting from initial value may fail, e.g. setting
161 // ObjectVectorValue from ""
162 // That's ok, so we still report success since construction is complete
163 NS_LOG_DEBUG("construct \"" << tid.GetName() << "::" << info.name << "\" from "
164 << where);
165 }
166 else
167 {
168 /*
169 One would think this is an error...
170
171 but there are cases where `attributes.Find(info.checker)`
172 returns a non-null value which still fails the `DoSet()` call.
173 For example, `value` is sometimes a real `PointerValue`
174 containing 0 as the pointed-to address. Since value
175 is not null (it just contains null) the initial
176 value is not used, the DoSet fails, and we end up
177 here.
178
179 If we were adventurous we might try to fix this deep
180 below DoSet, but there be dragons.
181 */
182 /*
183 NS_ASSERT_MSG(false,
184 "Failed to set attribute '" << info.name << "' from '"
185 << value->SerializeToString(info.checker)
186 << "'");
187 */
188 }
189 }
190 tid = tid.GetParent();
191 } while (tid != ObjectBase::GetTypeId());
193}
194
195bool
198 const AttributeValue& value)
199{
200 NS_LOG_FUNCTION(this << accessor << checker << &value);
201 Ptr<AttributeValue> v = checker->CreateValidValue(value);
202 if (!v)
203 {
204 return false;
205 }
206 bool ok = accessor->Set(this, *v);
207 return ok;
208}
209
210void
211ObjectBase::SetAttribute(std::string name, const AttributeValue& value)
212{
213 NS_LOG_FUNCTION(this << name << &value);
216 if (!tid.LookupAttributeByName(name, &info))
217 {
219 "Attribute name=" << name << " does not exist for this object: tid=" << tid.GetName());
220 }
221 if (!(info.flags & TypeId::ATTR_SET) || !info.accessor->HasSetter())
222 {
224 "Attribute name=" << name << " is not settable for this object: tid=" << tid.GetName());
225 }
226 if (!DoSet(info.accessor, info.checker, value))
227 {
228 NS_FATAL_ERROR("Attribute name=" << name << " could not be set for this object: tid="
229 << tid.GetName());
230 }
231}
232
233bool
235{
236 NS_LOG_FUNCTION(this << name << &value);
239 if (!tid.LookupAttributeByName(name, &info))
240 {
241 return false;
242 }
243 if (!(info.flags & TypeId::ATTR_SET) || !info.accessor->HasSetter())
244 {
245 return false;
246 }
247 return DoSet(info.accessor, info.checker, value);
248}
249
250void
251ObjectBase::GetAttribute(std::string name, AttributeValue& value, bool permissive) const
252{
253 NS_LOG_FUNCTION(this << name << &value);
256 if (!tid.LookupAttributeByName(name, &info, permissive))
257 {
259 "Attribute name=" << name << " does not exist for this object: tid=" << tid.GetName());
260 }
261 if (!(info.flags & TypeId::ATTR_GET) || !info.accessor->HasGetter())
262 {
264 "Attribute name=" << name << " is not gettable for this object: tid=" << tid.GetName());
265 }
266 bool ok = info.accessor->Get(this, value);
267 if (ok)
268 {
269 return;
270 }
271 auto str = dynamic_cast<StringValue*>(&value);
272 if (str == nullptr)
273 {
274 NS_FATAL_ERROR("Attribute name=" << name << " tid=" << tid.GetName()
275 << ": input value is not a string");
276 }
277 Ptr<AttributeValue> v = info.checker->Create();
278 ok = info.accessor->Get(this, *PeekPointer(v));
279 if (!ok)
280 {
281 NS_FATAL_ERROR("Attribute name=" << name << " tid=" << tid.GetName()
282 << ": could not get value");
283 }
284 str->Set(v->SerializeToString(info.checker));
285}
286
287bool
289{
290 NS_LOG_FUNCTION(this << name << &value);
293 if (!tid.LookupAttributeByName(name, &info))
294 {
295 return false;
296 }
297 if (!(info.flags & TypeId::ATTR_GET) || !info.accessor->HasGetter())
298 {
299 return false;
300 }
301 bool ok = info.accessor->Get(this, value);
302 if (ok)
303 {
304 return true;
305 }
306 auto str = dynamic_cast<StringValue*>(&value);
307 if (str == nullptr)
308 {
309 return false;
310 }
311 Ptr<AttributeValue> v = info.checker->Create();
312 ok = info.accessor->Get(this, *PeekPointer(v));
313 if (!ok)
314 {
315 return false;
316 }
317 str->Set(v->SerializeToString(info.checker));
318 return true;
319}
320
321bool
323{
324 NS_LOG_FUNCTION(this << name << &cb);
327 if (!accessor)
328 {
329 NS_LOG_DEBUG("Cannot connect trace " << name << " on object of type " << tid.GetName());
330 return false;
331 }
332 bool ok = accessor->ConnectWithoutContext(this, cb);
333 return ok;
334}
335
336bool
337ObjectBase::TraceConnect(std::string name, std::string context, const CallbackBase& cb)
338{
339 NS_LOG_FUNCTION(this << name << context << &cb);
342 if (!accessor)
343 {
344 NS_LOG_DEBUG("Cannot connect trace " << name << " on object of type " << tid.GetName());
345 return false;
346 }
347 bool ok = accessor->Connect(this, context, cb);
348 return ok;
349}
350
351bool
353{
354 NS_LOG_FUNCTION(this << name << &cb);
357 if (!accessor)
358 {
359 return false;
360 }
361 bool ok = accessor->DisconnectWithoutContext(this, cb);
362 return ok;
363}
364
365bool
366ObjectBase::TraceDisconnect(std::string name, std::string context, const CallbackBase& cb)
367{
368 NS_LOG_FUNCTION(this << name << context << &cb);
371 if (!accessor)
372 {
373 return false;
374 }
375 bool ok = accessor->Disconnect(this, context, cb);
376 return ok;
377}
378
379} // namespace ns3
NS_ABORT_x macro definitions.
ns3::AttributeConstructionList declaration.
uint32_t v
List of Attribute name, value and checker triples used to construct Objects.
Ptr< AttributeValue > Find(Ptr< const AttributeChecker > checker) const
Find an Attribute in the list from its AttributeChecker.
Hold a value for an Attribute.
Definition attribute.h:59
Base class for Callback class.
Definition callback.h:347
Callback template class.
Definition callback.h:428
friend class Callback
Definition callback.h:430
CallbackImpl class with varying numbers of argument types.
Definition callback.h:226
static KeyFoundType Get(const std::string &envvar, const std::string &key="", const std::string &delim=";")
Get the value corresponding to a key from an environment variable.
Anchor the ns-3 type and attribute system.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
bool TraceDisconnect(std::string name, std::string context, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected with a context.
static TypeId GetObjectIid()
Ensure the TypeId for ObjectBase gets fully configured to anchor the inheritance tree properly.
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
virtual TypeId GetInstanceTypeId() const =0
Get the most derived TypeId for this Object.
void ConstructSelf(const AttributeConstructionList &attributes)
Complete construction of ObjectBase; invoked by derived classes.
virtual ~ObjectBase()
Virtual destructor.
bool GetAttributeFailSafe(std::string name, AttributeValue &value) const
Get the value of an attribute without raising errors.
virtual void NotifyConstructionCompleted()
Notifier called once the ObjectBase is fully constructed.
static TypeId GetTypeId()
Get the type ID.
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
bool TraceConnect(std::string name, std::string context, const CallbackBase &cb)
Connect a TraceSource to a Callback with a context.
void GetAttribute(std::string name, AttributeValue &value, bool permissive=false) const
Get the value of an attribute, raising fatal errors if unsuccessful.
bool DoSet(Ptr< const AttributeAccessor > spec, Ptr< const AttributeChecker > checker, const AttributeValue &value)
Attempt to set the value referenced by the accessor spec to a valid value according to the checker,...
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
Hold variables of type string.
Definition string.h:45
a unique identifier for an interface.
Definition type-id.h:49
@ ATTR_GET
The attribute can be read.
Definition type-id.h:54
@ ATTR_SET
The attribute can be written.
Definition type-id.h:55
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition type-id.h:56
std::string GetAttributeFullName(std::size_t i) const
Get the Attribute name by index.
Definition type-id.cc:1183
std::size_t GetAttributeN() const
Get the number of attributes.
Definition type-id.cc:1168
TypeId GetParent() const
Get the parent of this TypeId.
Definition type-id.cc:1023
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition type-id.cc:1007
Ptr< const TraceSourceAccessor > LookupTraceSourceByName(std::string name) const
Find a TraceSource by name.
Definition type-id.cc:1266
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition type-id.cc:1176
static bool LookupByNameFailSafe(std::string name, TypeId *tid)
Get a TypeId by name.
Definition type-id.cc:884
bool LookupAttributeByName(std::string name, AttributeInformation *info, bool permissive=false) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition type-id.cc:966
std::string GetName() const
Get the name.
Definition type-id.cc:1059
Class Environment declaration.
NS_FATAL_x macro definitions.
template Callback< ObjectBase * > MakeCallback< ObjectBase * >(ObjectBase *(*)())
Explicit instantiation for ObjectBase.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:454
Debug message logging.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:463
ns3::ObjectBase declaration and NS_OBJECT_ENSURE_REGISTERED() macro definition.
ns3::StringValue attribute value declarations.
Attribute implementation.
Definition type-id.h:86
std::string name
Attribute name.
Definition type-id.h:88
Ptr< const AttributeAccessor > accessor
Accessor object.
Definition type-id.h:98
uint32_t flags
AttributeFlags value.
Definition type-id.h:92
Ptr< const AttributeChecker > checker
Checker object.
Definition type-id.h:100
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition type-id.h:96
ns3::TraceSourceAccessor and ns3::MakeTraceSourceAccessor declarations.