opp_component_ptr.h Source File

API: opp_component_ptr.h Source File
API
opp_component_ptr.h
1//==========================================================================
2// OPP_COMPONENT_PTR.H - header for
3// OMNeT++/OMNEST
4// Discrete System Simulation in C++
5//
6//==========================================================================
7
8/*--------------------------------------------------------------*
9 Copyright (C) 1992-2017 Andras Varga
10 Copyright (C) 2006-2017 OpenSim Ltd.
11
12 This file is distributed WITHOUT ANY WARRANTY. See the file
13 `license' for details on this and other legal matters.
14*--------------------------------------------------------------*/
15
16#ifndef __OMNETPP_OPP_COMPONENT_PTR_H
17#define __OMNETPP_OPP_COMPONENT_PTR_H
18
19#include "cmodule.h"
20#include "cexception.h"
21
22namespace omnetpp {
23
55template <typename T>
56class SIM_API opp_component_ptr
57{
58 private:
59 T *ptr = nullptr;
60
61 void registerPtr() {
62 if (ptr) {
63 if (cComponent *component = dynamic_cast<cComponent*>(ptr))
64 component->registerSelfPointer(ptr);
65 else
66 throw cRuntimeError("opp_component_ptr<%s>: Pointer cannot be dynamic_cast to cComponent", opp_typename(typeid(T)));
67 }
68 }
69
70 void deregisterPtr() {
71 if (ptr)
72 dynamic_cast<cComponent*>(ptr)->deregisterSelfPointer(ptr);
73 }
74
75 void checkNull() const {
76 if (ptr == nullptr)
77 throw cRuntimeError("opp_component_ptr<%s>: Cannot dereference nullptr", opp_typename(typeid(T)));
78 }
79
80 void doResolveFromPar(cModule *context, const char *parName, bool optional) {
81 const char *methodName = optional ? "resolveFromParOptional" : "resolveFromPar";
82 if (!context)
83 throw cRuntimeError("opp_component_ptr<%s>::%s(): context module is nullptr", opp_typename(typeid(T)), methodName);
84 if (!parName)
85 throw cRuntimeError("opp_component_ptr<%s>::%s(): parameter name is nullptr", opp_typename(typeid(T)), methodName);
86 const char *path = context->par(parName).stringValue();
87 if (!*path) {
88 if (!optional)
89 throw cRuntimeError("opp_component_ptr<%s>::%s(): parameter '%s' of module '(%s)%s' is empty",
90 opp_typename(typeid(T)), methodName, parName, context->getClassName(), context->getFullPath().c_str());
91 *this = nullptr;
92 return;
93 }
94 cModule *mod = context->findModuleByPath(path);
95 if (!mod)
96 throw cRuntimeError("opp_component_ptr<%s>::%s(): module '%s' not found, referenced by parameter '%s' of module '(%s)%s'",
97 opp_typename(typeid(T)), methodName, path, parName, context->getClassName(), context->getFullPath().c_str());
98 T *t = dynamic_cast<T *>(mod);
99 if (!t)
100 throw cRuntimeError("opp_component_ptr<%s>::%s(): module '(%s)%s' resolved from parameter '%s' of module '(%s)%s' cannot be cast to type '%s'",
101 opp_typename(typeid(T)), methodName, mod->getClassName(), mod->getFullPath().c_str(), parName, context->getClassName(), context->getFullPath().c_str(), opp_typename(typeid(T)));
102 *this = t;
103 }
104
105 cGate *doResolveFromGate(cGate *gate, int direction, bool optional) {
106 const char *methodName = optional ? "resolveFromGateOptional" : "resolveFromGate";
107 if (!gate)
108 throw cRuntimeError("opp_component_ptr<%s>::%s(): gate is nullptr", opp_typename(typeid(T)), methodName);
109
110 bool forward;
111 if (direction > 0)
112 forward = true;
113 else if (direction < 0)
114 forward = false;
115 else if (gate->getType() == cGate::OUTPUT)
116 forward = true;
117 else if (gate->getType() == cGate::INPUT)
118 forward = false;
119 else
120 throw cRuntimeError("opp_component_ptr<%s>::%s(): cannot determine direction for gate '%s'",
121 opp_typename(typeid(T)), methodName, gate->getFullPath().c_str());
122
123 cGate *g = forward ? gate->getNextGate() : gate->getPreviousGate();
124 while (g) {
125 if (T *t = dynamic_cast<T *>(g->getOwnerModule())) {
126 *this = t;
127 return g;
128 }
129 g = forward ? g->getNextGate() : g->getPreviousGate();
130 }
131
132 if (!optional)
133 throw cRuntimeError("opp_component_ptr<%s>::%s(): no module of type '%s' found along the connection path from gate '%s'",
134 opp_typename(typeid(T)), methodName, opp_typename(typeid(T)), gate->getFullPath().c_str());
135 *this = nullptr;
136 return nullptr;
137 }
138
139 public:
144
149 opp_component_ptr(T *ptr) : ptr(ptr) {registerPtr();}
150
155 opp_component_ptr(const opp_component_ptr<T>& other) : ptr(other.ptr) {registerPtr();}
156
160 ~opp_component_ptr() {deregisterPtr();}
161
166 T& operator*() const {checkNull(); return *ptr;}
167
172 T *operator->() const {checkNull(); return ptr;}
173
177 operator T *() const {return ptr;}
178
182 explicit operator bool() const {return ptr != nullptr;}
183
188 void operator=(T *newPtr) {
189 if (ptr != newPtr) {
190 deregisterPtr();
191 ptr = newPtr;
192 registerPtr();
193 }
194 }
195
200 void operator=(const opp_component_ptr<T>& ref) {*this = ref.ptr;}
201
206 T *get() const {checkNull(); return ptr;}
207
211 T *getNullable() const {return ptr;}
212
220 void resolveFromParOptional(cModule *context, const char *parName) {
221 doResolveFromPar(context, parName, true);
222 }
223
230 void resolveFromPar(cModule *context, const char *parName) {
231 doResolveFromPar(context, parName, false);
232 }
233
246 cGate *resolveFromGateOptional(cGate *gate, int direction = 0) {
247 return doResolveFromGate(gate, direction, true);
248 }
249
262 cGate *resolveFromGate(cGate *gate, int direction = 0) {
263 return doResolveFromGate(gate, direction, false);
264 }
265};
266
267} // namespace omnetpp
268
269#endif
270
Common base for module and channel classes.
Definition ccomponent.h:51
virtual cPar & par(int k)
virtual cModule * findModuleByPath(const char *path) const
Represents a module gate.
Definition cgate.h:63
cGate * getNextGate() const
Definition cgate.h:465
cGate * getPreviousGate() const
Definition cgate.h:458
cModule * getOwnerModule() const
Type getType() const
Definition cgate.h:289
This class represents modules in the simulation.
Definition cmodule.h:49
virtual std::string getFullPath() const override
virtual const char * getClassName() const
virtual std::string getFullPath() const
const char * stringValue() const
Thrown when the simulation kernel or other components detect a runtime error.
Definition cexception.h:343
T & operator*() const
Definition opp_component_ptr.h:166
opp_component_ptr(const opp_component_ptr< T > &other)
Definition opp_component_ptr.h:155
void resolveFromPar(cModule *context, const char *parName)
Definition opp_component_ptr.h:230
T * getNullable() const
Definition opp_component_ptr.h:211
opp_component_ptr()
Definition opp_component_ptr.h:143
void operator=(T *newPtr)
Definition opp_component_ptr.h:188
opp_component_ptr(T *ptr)
Definition opp_component_ptr.h:149
void operator=(const opp_component_ptr< T > &ref)
Definition opp_component_ptr.h:200
T * operator->() const
Definition opp_component_ptr.h:172
cGate * resolveFromGate(cGate *gate, int direction=0)
Definition opp_component_ptr.h:262
~opp_component_ptr()
Definition opp_component_ptr.h:160
cGate * resolveFromGateOptional(cGate *gate, int direction=0)
Definition opp_component_ptr.h:246
void resolveFromParOptional(cModule *context, const char *parName)
Definition opp_component_ptr.h:220
T * get() const
Definition opp_component_ptr.h:206
SIM_API const char * opp_typename(const std::type_info &t)
Returns the name of a C++ type, correcting the quirks of various compilers.