Statistics
| Branch: | Revision:

root / src / sim / ccomponenttype.cc @ e1750c09

History | View | Annotate | Download (10.6 KB)

1
//=========================================================================
2
//  CCOMPONENTTYPE.CC - part of
3
//
4
//                    OMNeT++/OMNEST
5
//             Discrete System Simulation in C++
6
//
7
//=========================================================================
8

    
9
/*--------------------------------------------------------------*
10
  Copyright (C) 1992-2008 Andras Varga
11
  Copyright (C) 2006-2008 OpenSim Ltd.
12

13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16

    
17
#include <string.h>
18
#include "ccomponenttype.h"
19
#include "cmodule.h"
20
#include "csimplemodule.h"
21
#include "ccompoundmodule.h"
22
#include "cchannel.h"
23
#include "cenvir.h"
24
#include "cparimpl.h"
25
#include "cexception.h"
26
#include "globals.h"
27
#include "cdelaychannel.h"
28
#include "cdataratechannel.h"
29
#include "cmodelchange.h"
30

    
31
#ifdef WITH_PARSIM
32
#include "ccommbuffer.h"
33
#include "parsim/cplaceholdermod.h"
34
#endif
35

    
36
USING_NAMESPACE
37

    
38
cComponentType::cComponentType(const char *qname) : cNoncopyableOwnedObject(qname,false)
39
{
40
    // store fully qualified name, and set name to simple (unqualified) name
41
    qualifiedName = qname;
42
    const char *lastDot = strrchr(qname, '.');
43
    setName(!lastDot ? qname : lastDot + 1);
44
}
45

    
46
cComponentType::~cComponentType()
47
{
48
    for (StringToParMap::iterator it = sharedParMap.begin(); it!=sharedParMap.end(); ++it)
49
        delete it->second;
50
    for (ParImplSet::iterator it = sharedParSet.begin(); it!=sharedParSet.end(); ++it)
51
        delete *it;
52
}
53

    
54
cComponentType *cComponentType::find(const char *qname)
55
{
56
    return dynamic_cast<cComponentType *>(componentTypes.getInstance()->lookup(qname));
57
}
58

    
59
cComponentType *cComponentType::get(const char *qname)
60
{
61
    cComponentType *p = find(qname);
62
    if (!p) {
63
        const char *hint = (!qname || !strchr(qname,'.')) ? " (fully qualified type name expected)" : "";
64
        throw cRuntimeError("NED type \"%s\" not found%s", qname, hint);
65
    }
66
    return p;
67
}
68

    
69
cParImpl *cComponentType::getSharedParImpl(const char *key) const
70
{
71
    StringToParMap::const_iterator it = sharedParMap.find(key);
72
    return it==sharedParMap.end() ? NULL : it->second;
73
}
74

    
75
void cComponentType::putSharedParImpl(const char *key, cParImpl *value)
76
{
77
    ASSERT(sharedParMap.find(key)==sharedParMap.end()); // not yet in there
78
    value->setIsShared(true);
79
    sharedParMap[key] = value;
80
}
81

    
82
// cannot go inline due to declaration order
83
bool cComponentType::Less::operator()(cParImpl *a, cParImpl *b) const
84
{
85
    return a->compare(b) < 0;
86
}
87

    
88
cParImpl *cComponentType::getSharedParImpl(cParImpl *value) const
89
{
90
    ParImplSet::const_iterator it = sharedParSet.find(value);
91
    return it==sharedParSet.end() ? NULL : *it;
92
}
93

    
94
void cComponentType::putSharedParImpl(cParImpl *value)
95
{
96
    ASSERT(sharedParSet.find(value)==sharedParSet.end()); // not yet in there
97
    value->setIsShared(true);
98
    sharedParSet.insert(value);
99
}
100

    
101
//----
102

    
103
cModuleType::cModuleType(const char *name) : cComponentType(name)
104
{
105
}
106

    
107
cModule *cModuleType::create(const char *modname, cModule *parentmod)
108
{
109
    return create(modname, parentmod, -1, 0);
110
}
111

    
112
cModule *cModuleType::create(const char *modname, cModule *parentmod, int vectorsize, int index)
113
{
114
    // notify pre-change listeners
115
    if (parentmod && parentmod->hasListeners(PRE_MODEL_CHANGE)) {
116
        cPreModuleAddNotification tmp;
117
        tmp.moduleType = this;
118
        tmp.moduleName = modname;
119
        tmp.parentModule = parentmod;
120
        tmp.vectorSize = vectorsize;
121
        tmp.index = index;
122
        parentmod->emit(PRE_MODEL_CHANGE, &tmp);
123
    }
124

    
125
    // set context type to "BUILD"
126
    cContextTypeSwitcher tmp(CTX_BUILD);
127

    
128
    // Object members of the new module class are collected to tmplist.
129
    cDefaultList tmplist;
130
    cDefaultList *oldlist = cOwnedObject::getDefaultOwner();
131
    cOwnedObject::setDefaultOwner(&tmplist);
132
    cModule *mod;
133
    try {
134
        // create the new module object
135
#ifdef WITH_PARSIM
136
        bool isLocal = ev.isModuleLocal(parentmod, modname, index);
137
        mod = isLocal ? createModuleObject() : new cPlaceholderModule();
138
#else
139
        mod = createModuleObject();
140
#endif
141
    }
142
    catch (std::exception& e) {
143
        // restore defaultowner, otherwise it'll remain pointing to a dead object
144
        cOwnedObject::setDefaultOwner(oldlist);
145
        throw;
146
    }
147

    
148
    // set up module: set name, module type, vector size, parent
149
    mod->setName(modname);
150
    mod->setComponentType(this);
151
    if (vectorsize>=0)
152
        mod->setIndex(index, vectorsize);
153
    if (parentmod)
154
        parentmod->insertSubmodule(mod);
155

    
156
    // set system module (must be done before takeAllObjectsFrom(tmplist) because
157
    // if parentmod==NULL, mod itself is on tmplist)
158
    if (!parentmod)
159
         simulation.setSystemModule(mod);
160

    
161
    // put the object members of the new module to their place
162
    mod->takeAllObjectsFrom(tmplist);
163

    
164
    // restore defaultowner (must precede parameters)
165
    cOwnedObject::setDefaultOwner(oldlist);
166

    
167
    // register with cSimulation
168
    int id = simulation.registerModule(mod);
169
    mod->setId(id);
170

    
171
    // set up RNG mapping
172
    ev.getRNGMappingFor(mod);
173

    
174
    // add parameters and gates to the new module;
175
    // note: setupGateVectors() will be called from finalizeParameters()
176
    addParametersAndGatesTo(mod);
177

    
178
    // notify envir
179
    ev.configure(mod);
180
    EVCB.moduleCreated(mod);
181

    
182
    // notify post-change listeners
183
    if (mod->hasListeners(POST_MODEL_CHANGE)) {
184
        cPostModuleAddNotification tmp;
185
        tmp.module = mod;
186
        mod->emit(POST_MODEL_CHANGE, &tmp);
187
    }
188

    
189
    // done -- if it's a compound module, buildInside() will do the rest
190
    return mod;
191
}
192

    
193
cModule *cModuleType::instantiateModuleClass(const char *classname)
194
{
195
    cObject *obj = cObjectFactory::createOne(classname); // this won't return NULL
196
    cModule *mod = dynamic_cast<cModule *>(obj);
197
    if (!mod)
198
        throw cRuntimeError("incorrect module class %s: not subclassed from cModule", classname);
199

    
200
    // check module object
201
    if (!mod->isModule())
202
        throw cRuntimeError("incorrect module class %s: isModule() returns false", classname);
203

    
204
    if (isSimple()) {
205
        if (dynamic_cast<cSimpleModule *>(mod)==NULL)
206
            throw cRuntimeError("incorrect simple module class %s: not subclassed from cSimpleModule", classname);
207
        if (mod->isSimple()==false)
208
            throw cRuntimeError("incorrect simple module class %s: isSimple() returns false", classname);
209
    }
210
    else {
211
        if (dynamic_cast<cCompoundModule *>(mod)==NULL)
212
            throw cRuntimeError("incorrect compound module class %s: not subclassed from cCompoundModule", classname);
213
        if (mod->isSimple()==true)
214
            throw cRuntimeError("incorrect compound module class %s: isSimple() returns true", classname);
215
    }
216

    
217
    return mod;
218
}
219

    
220
cModule *cModuleType::createScheduleInit(const char *modname, cModule *parentmod)
221
{
222
    if (!parentmod)
223
        throw cRuntimeError("createScheduleInit(): parent module pointer cannot be NULL "
224
                            "when creating module named '%s' of type %s", modname, getFullName());
225
    cModule *mod = create(modname, parentmod);
226
    mod->finalizeParameters();
227
    mod->buildInside();
228
    mod->scheduleStart(simulation.getSimTime());
229
    mod->callInitialize();
230
    return mod;
231
}
232

    
233
cModuleType *cModuleType::find(const char *qname)
234
{
235
    return dynamic_cast<cModuleType *>(componentTypes.getInstance()->lookup(qname));
236
}
237

    
238
cModuleType *cModuleType::get(const char *qname)
239
{
240
    cModuleType *p = find(qname);
241
    if (!p) {
242
        const char *hint = (!qname || !strchr(qname,'.')) ? " (fully qualified type name expected)" : "";
243
        throw cRuntimeError("NED module type \"%s\" not found%s", qname, hint);
244
    }
245
    return p;
246
}
247

    
248
//----
249

    
250
cChannelType *cChannelType::idealChannelType;
251
cChannelType *cChannelType::delayChannelType;
252
cChannelType *cChannelType::datarateChannelType;
253

    
254
cChannelType::cChannelType(const char *name) : cComponentType(name)
255
{
256
}
257

    
258
cChannel *cChannelType::instantiateChannelClass(const char *classname)
259
{
260
    cObject *obj = cObjectFactory::createOne(classname); // this won't return NULL
261
    cChannel *channel = dynamic_cast<cChannel *>(obj);
262
    if (!channel)
263
        throw cRuntimeError("class %s is not a channel type", classname); //FIXME better msg
264
    return channel;
265
}
266

    
267
cChannel *cChannelType::create(const char *name)
268
{
269
    cContextTypeSwitcher tmp(CTX_BUILD);
270

    
271
    // Object members of the new channel class are collected to tmplist.
272
    cDefaultList tmplist;
273
    cDefaultList *oldlist = cOwnedObject::getDefaultOwner();
274
    cOwnedObject::setDefaultOwner(&tmplist);
275

    
276
    // create channel object
277
    cChannel *channel;
278
    try {
279
        channel = createChannelObject();
280
    }
281
    catch (std::exception& e) {
282
        // restore defaultowner, otherwise it'll remain pointing to a dead object
283
        cOwnedObject::setDefaultOwner(oldlist);
284
        throw;
285
    }
286

    
287
    // set up channel: set name, channel type, etc
288
    channel->setName(name);
289
    channel->setComponentType(this);
290

    
291
    // put the object members of the new module to their place
292
    oldlist->take(channel);
293
    channel->takeAllObjectsFrom(tmplist);
294

    
295
    // restore defaultowner
296
    cOwnedObject::setDefaultOwner(oldlist);
297

    
298
    // set up RNG mapping
299
    ev.getRNGMappingFor(channel);
300

    
301
    // add parameters to the new module
302
    addParametersTo(channel);
303

    
304
    return channel;
305
}
306

    
307
cChannelType *cChannelType::find(const char *qname)
308
{
309
    return dynamic_cast<cChannelType *>(componentTypes.getInstance()->lookup(qname));
310
}
311

    
312
cChannelType *cChannelType::get(const char *qname)
313
{
314
    cChannelType *p = find(qname);
315
    if (!p) {
316
        const char *hint = (!qname || !strchr(qname,'.')) ? " (fully qualified type name expected)" : "";
317
        throw cRuntimeError("NED channel type \"%s\" not found%s", qname, hint);
318
    }
319
    return p;
320
}
321

    
322
cChannelType *cChannelType::getIdealChannelType()
323
{
324
    if (!idealChannelType) {
325
        idealChannelType = find("ned.IdealChannel");
326
        ASSERT(idealChannelType);
327
    }
328
    return idealChannelType;
329
}
330

    
331
cChannelType *cChannelType::getDelayChannelType()
332
{
333
    if (!delayChannelType) {
334
        delayChannelType = find("ned.DelayChannel");
335
        ASSERT(delayChannelType);
336
    }
337
    return delayChannelType;
338
}
339

    
340
cChannelType *cChannelType::getDatarateChannelType()
341
{
342
    if (!datarateChannelType) {
343
        datarateChannelType = find("ned.DatarateChannel");
344
        ASSERT(datarateChannelType);
345
    }
346
    return datarateChannelType;
347
}
348

    
349
cIdealChannel *cChannelType::createIdealChannel(const char *name)
350
{
351
    return cIdealChannel::create(name);
352
}
353

    
354
cDelayChannel *cChannelType::createDelayChannel(const char *name)
355
{
356
    return cDelayChannel::create(name);
357
}
358

    
359
cDatarateChannel *cChannelType::createDatarateChannel(const char *name)
360
{
361
    return cDatarateChannel::create(name);
362
}
363

    
364