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 "assert.h"
13#include "log.h"
14#include "string.h"
16
17#include "ns3/core-config.h"
18
19/**
20 * @file
21 * @ingroup object
22 * ns3::ObjectBase class implementation.
23 */
24
25namespace ns3
26{
27// Explicit instantiation declaration
28
29/**
30 * @ingroup callback
31 * Explicit instantiation for ObjectBase
32 * @return A wrapper Callback
33 * \sa ns3::MakeCallback
34 */
37template class CallbackImpl<ObjectBase*>;
38
39NS_LOG_COMPONENT_DEFINE("ObjectBase");
40
42
43/**
44 * Ensure the TypeId for ObjectBase gets fully configured
45 * to anchor the inheritance tree properly.
46 *
47 * @relates ns3::ObjectBase
48 *
49 * @return The TypeId for ObjectBase.
50 */
51static TypeId
53{
55 TypeId tid = TypeId("ns3::ObjectBase");
56 tid.SetParent(tid);
57 tid.SetGroupName("Core");
58 return tid;
59}
60
63{
65 static TypeId tid = GetObjectIid();
66 return tid;
67}
68
73
74void
79
80void
82{
83 // loop over the inheritance tree back to the Object base class.
84 NS_LOG_FUNCTION(this << &attributes);
86 TypeId objectTid;
87 // the TypeId of a class derived from Object is initialized to "ns3::Object"; for a class
88 // deriving from Object, check that this function is called after that the correct TypeId is set
89 // to ensure that the attributes of the class are initialized
90 NS_ABORT_MSG_IF(TypeId::LookupByNameFailSafe("ns3::Object", &objectTid) && tid == objectTid,
91 "ObjectBase::ConstructSelf() has been called on an object of a class derived "
92 "from the Object class, but the TypeId is still set to ns3::Object.\n"
93 "This is known to happen in two cases:\n"
94 "- ObjectBase::ConstructSelf() is called in the class constructor; in this "
95 "case, override ObjectBase::NotifyConstructionCompleted() to access the "
96 "initial values of the object attributes as soon as object construction is "
97 "completed (see issue #1249)\n"
98 "- the class deriving from Object does not define a static GetTypeId() method");
99 do // Do this tid and all parents
100 {
101 // loop over all attributes in object type
102 NS_LOG_DEBUG("construct tid=" << tid.GetName() << ", params=" << tid.GetAttributeN());
103 for (uint32_t i = 0; i < tid.GetAttributeN(); i++)
104 {
106 NS_LOG_DEBUG("try to construct \"" << tid.GetName() << "::" << info.name << "\"");
107 // is this attribute stored in this AttributeConstructionList instance ?
108 Ptr<const AttributeValue> value = attributes.Find(info.checker);
109 std::string where = "argument";
110
111 // See if this attribute should not be set here in the
112 // constructor.
113 if (!(info.flags & TypeId::ATTR_CONSTRUCT))
114 {
115 // Handle this attribute if it should not be
116 // set here.
117 if (!value)
118 {
119 // Skip this attribute if it's not in the
120 // AttributeConstructionList.
121 NS_LOG_DEBUG("skipping, not settable at construction");
122 continue;
123 }
124 else
125 {
126 // This is an error because this attribute is not
127 // settable in its constructor but is present in
128 // the AttributeConstructionList.
129 NS_FATAL_ERROR("Attribute name="
130 << info.name << " tid=" << tid.GetName()
131 << ": initial value cannot be set using attributes");
132 }
133 }
134
135 if (!value)
136 {
137 NS_LOG_DEBUG("trying to set from environment variable NS_ATTRIBUTE_DEFAULT");
138 auto [found, val] =
139 EnvironmentVariable::Get("NS_ATTRIBUTE_DEFAULT", tid.GetAttributeFullName(i));
140 if (found)
141 {
142 NS_LOG_DEBUG("found in environment: " << val);
143 value = Create<StringValue>(val);
144 where = "env var";
145 }
146 }
147
148 bool initial{false};
149 if (!value)
150 {
151 // This is guaranteed to exist
152 NS_LOG_DEBUG("falling back to initial value from tid");
153 value = info.initialValue;
154 where = "initial value";
155 initial = true;
156 }
157
158 // We have a matching attribute value, if only from the initialValue
159 if (DoSet(info.accessor, info.checker, *value) || initial)
160 {
161 // Setting from initial value may fail, e.g. setting
162 // ObjectVectorValue from ""
163 // That's ok, so we still report success since construction is complete
164 NS_LOG_DEBUG("construct \"" << tid.GetName() << "::" << info.name << "\" from "
165 << where);
166 }
167 else
168 {
169 /*
170 One would think this is an error...
171
172 but there are cases where `attributes.Find(info.checker)`
173 returns a non-null value which still fails the `DoSet()` call.
174 For example, `value` is sometimes a real `PointerValue`
175 containing 0 as the pointed-to address. Since value
176 is not null (it just contains null) the initial
177 value is not used, the DoSet fails, and we end up
178 here.
179
180 If we were adventurous we might try to fix this deep
181 below DoSet, but there be dragons.
182 */
183 /*
184 NS_ASSERT_MSG(false,
185 "Failed to set attribute '" << info.name << "' from '"
186 << value->SerializeToString(info.checker)
187 << "'");
188 */
189 }
190 }
191 tid = tid.GetParent();
192 } while (tid != ObjectBase::GetTypeId());
194}
195
196bool
199 const AttributeValue& value)
200{
201 NS_LOG_FUNCTION(this << accessor << checker << &value);
202 Ptr<AttributeValue> v = checker->CreateValidValue(value);
203 if (!v)
204 {
205 return false;
206 }
207 bool ok = accessor->Set(this, *v);
208 return ok;
209}
210
211void
212ObjectBase::SetAttribute(std::string name, const AttributeValue& value)
213{
214 NS_LOG_FUNCTION(this << name << &value);
217 if (!tid.LookupAttributeByName(name, &info))
218 {
220 "Attribute name=" << name << " does not exist for this object: tid=" << tid.GetName());
221 }
222 if (!(info.flags & TypeId::ATTR_SET) || !info.accessor->HasSetter())
223 {
225 "Attribute name=" << name << " is not settable for this object: tid=" << tid.GetName());
226 }
227 if (!DoSet(info.accessor, info.checker, value))
228 {
229 NS_FATAL_ERROR("Attribute name=" << name << " could not be set for this object: tid="
230 << tid.GetName());
231 }
232}
233
234bool
236{
237 NS_LOG_FUNCTION(this << name << &value);
240 if (!tid.LookupAttributeByName(name, &info))
241 {
242 return false;
243 }
244 if (!(info.flags & TypeId::ATTR_SET) || !info.accessor->HasSetter())
245 {
246 return false;
247 }
248 return DoSet(info.accessor, info.checker, value);
249}
250
251void
252ObjectBase::GetAttribute(std::string name, AttributeValue& value, bool permissive) const
253{
254 NS_LOG_FUNCTION(this << name << &value);
257 if (!tid.LookupAttributeByName(name, &info, permissive))
258 {
260 "Attribute name=" << name << " does not exist for this object: tid=" << tid.GetName());
261 }
262 if (!(info.flags & TypeId::ATTR_GET) || !info.accessor->HasGetter())
263 {
265 "Attribute name=" << name << " is not gettable for this object: tid=" << tid.GetName());
266 }
267 bool ok = info.accessor->Get(this, value);
268 if (ok)
269 {
270 return;
271 }
272 auto str = dynamic_cast<StringValue*>(&value);
273 if (str == nullptr)
274 {
275 NS_FATAL_ERROR("Attribute name=" << name << " tid=" << tid.GetName()
276 << ": input value is not a string");
277 }
278 Ptr<AttributeValue> v = info.checker->Create();
279 ok = info.accessor->Get(this, *PeekPointer(v));
280 if (!ok)
281 {
282 NS_FATAL_ERROR("Attribute name=" << name << " tid=" << tid.GetName()
283 << ": could not get value");
284 }
285 str->Set(v->SerializeToString(info.checker));
286}
287
288bool
290{
291 NS_LOG_FUNCTION(this << name << &value);
294 if (!tid.LookupAttributeByName(name, &info))
295 {
296 return false;
297 }
298 if (!(info.flags & TypeId::ATTR_GET) || !info.accessor->HasGetter())
299 {
300 return false;
301 }
302 bool ok = info.accessor->Get(this, value);
303 if (ok)
304 {
305 return true;
306 }
307 auto str = dynamic_cast<StringValue*>(&value);
308 if (str == nullptr)
309 {
310 return false;
311 }
312 Ptr<AttributeValue> v = info.checker->Create();
313 ok = info.accessor->Get(this, *PeekPointer(v));
314 if (!ok)
315 {
316 return false;
317 }
318 str->Set(v->SerializeToString(info.checker));
319 return true;
320}
321
322bool
324{
325 NS_LOG_FUNCTION(this << name << &cb);
328 if (!accessor)
329 {
330 NS_LOG_DEBUG("Cannot connect trace " << name << " on object of type " << tid.GetName());
331 return false;
332 }
333 bool ok = accessor->ConnectWithoutContext(this, cb);
334 return ok;
335}
336
337bool
338ObjectBase::TraceConnect(std::string name, std::string context, const CallbackBase& cb)
339{
340 NS_LOG_FUNCTION(this << name << context << &cb);
343 if (!accessor)
344 {
345 NS_LOG_DEBUG("Cannot connect trace " << name << " on object of type " << tid.GetName());
346 return false;
347 }
348 bool ok = accessor->Connect(this, context, cb);
349 return ok;
350}
351
352bool
354{
355 NS_LOG_FUNCTION(this << name << &cb);
358 if (!accessor)
359 {
360 return false;
361 }
362 bool ok = accessor->DisconnectWithoutContext(this, cb);
363 return ok;
364}
365
366bool
367ObjectBase::TraceDisconnect(std::string name, std::string context, const CallbackBase& cb)
368{
369 NS_LOG_FUNCTION(this << name << context << &cb);
372 if (!accessor)
373 {
374 return false;
375 }
376 bool ok = accessor->Disconnect(this, context, cb);
377 return ok;
378}
379
380} // namespace ns3
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
ns3::AttributeConstructionList declaration.
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:344
Callback template class.
Definition callback.h:422
friend class Callback
Definition callback.h:424
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:67
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:1185
std::size_t GetAttributeN() const
Get the number of attributes.
Definition type-id.cc:1170
TypeId GetParent() const
Get the parent of this TypeId.
Definition type-id.cc:1025
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition type-id.cc:1009
Ptr< const TraceSourceAccessor > LookupTraceSourceByName(std::string name) const
Find a TraceSource by name.
Definition type-id.cc:1268
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition type-id.cc:1178
static bool LookupByNameFailSafe(std::string name, TypeId *tid)
Get a TypeId by name.
Definition type-id.cc:886
bool LookupAttributeByName(std::string name, AttributeInformation *info, bool permissive=false) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition type-id.cc:968
std::string GetName() const
Get the name.
Definition type-id.cc:1061
Class Environment declaration.
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:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:439
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:448
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.