Project

General

Profile

Statistics
| Branch: | Revision:

root / include / csimulation.h @ aeae20a1

History | View | Annotate | Download (20.1 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//   CSIMULATION.H  -  header for
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//
7
//  Declaration of the following classes:
8
//    cSimulation  : simulation management class; only one instance
9
//
10
//==========================================================================
11
12
/*--------------------------------------------------------------*
13
  Copyright (C) 1992-2008 Andras Varga
14
  Copyright (C) 2006-2008 OpenSim Ltd.
15

16
  This file is distributed WITHOUT ANY WARRANTY. See the file
17
  `license' for details on this and other legal matters.
18
*--------------------------------------------------------------*/
19
20
#ifndef __CSIMULATION_H
21
#define __CSIMULATION_H
22
23
#include "simkerneldefs.h"
24
#include "simtime_t.h"
25
#include "cmessageheap.h"
26
#include "cexception.h"
27
28
#include "clockedmsgheap.h"
29 93d0d4d3 Simon Tenbusch
#include "clock.h"
30
#include "cttaslock.h"
31
32 01873262 Georg Kunz
#include "cthreadpool.h"
33
#include "cstopwatch.h"
34 52072b74 Simon Tenbusch
#include "cscheduler.h"
35 01873262 Georg Kunz
#include <list>
36
37
NAMESPACE_BEGIN
38
39
//=== classes mentioned:
40
class  cMessage;
41
class  cGate;
42
class  cModule;
43
class  cSimpleModule;
44
class  cCompoundModule;
45
class  cSimulation;
46
class  cException;
47
class  cScheduler;
48
class  cParsimPartition;
49
class  cNEDFileLoader;
50
class  cHasher;
51
class  cModuleType;
52
class  cEnvir;
53
class  cDefaultList;
54
class  cThreadPool;
55
class  cAsyncModule;
56
57
SIM_API extern cDefaultList defaultList; // also in globals.h
58
59
/**
60
 * The active simulation manager instance.
61
 *
62
 * @ingroup SimCore
63
 */
64
#define simulation  (*cSimulation::getActiveSimulation())
65
66
67
/**
68
 * Simulation manager class.  cSimulation is the central class in \opp.
69
 * It stores the active simulation model, and provides methods for setting up,
70
 * running and finalizing simulations.
71
 *
72
 * Most cSimulation methods are not of interest for simulation model code,
73
 * they are used internally (e.g. by the user interface libraries (Envir,
74
 * Cmdenv, Tkenv) to set up and run simulations).
75
 *
76
 * Some methods which can be of interest when programming simple modules:
77
 * getUniqueNumber(), getModuleByPath(), getModule(), snapshot().
78
 *
79
 * @ingroup SimCore
80
 * @ingroup Internals
81
 */
82
class SIM_API cSimulation : public cNamedObject, noncopyable
83
{
84
    friend class cSimpleModule;
85
    friend class cThreadPool;
86
    friend class cLockedThreadPool;
87
    friend class cSpinningThreadPool;
88
89
  private:
90
    // global variables
91
    static cSimulation *simPtr; // the active cSimulation instance
92
    static cEnvir *evPtr;       // the active cEnvir instance
93
    static cEnvir *staticEvPtr; // the environment to activate when simPtr becomes NULL
94
95
    // variables of the module vector
96
    int size;                 // size of vector
97
    int delta;                // if needed, grows by delta
98
    cModule **vect;           // vector of modules, vect[0] is not used
99
    int last_id;              // index of last used pos. in vect[]
100
101
    // simulation vars
102
    cEnvir *ownEvPtr;         // the environment that belongs to this simulation object
103
    cModule *systemmodp;      // pointer to system (root) module
104
    cSimpleModule *activitymodp; // the module currently executing activity() (NULL if handleMessage() or in main)
105
    //cComponent *contextmodp;  // component in context (or NULL)
106
    int contexttype;          // the innermost context type (one of CTX_BUILD, CTX_EVENT, CTX_INITIALIZE, CTX_FINISH)
107
    cModuleType *networktype; // network type
108
    cScheduler *schedulerp;   // event scheduler
109
    simtime_t warmup_period;  // warm-up period
110
111
    int simulationstage;      // simulation stage (one of CTX_NONE, CTX_BUILD, CTX_EVENT, CTX_INITIALIZE, CTX_FINISH or CTX_CLEANUP)
112
    //simtime_t sim_time;       // simulation time (time of current event)
113
    eventnumber_t event_num;  // sequence number of current event
114
115
    cMessage *msg_for_activity; // helper variable to pass the received message into activity()
116
    cException *exception;    // helper variable to get exceptions back from activity()
117
118
    cHasher *hasherp;         // used for fingerprint calculation
119
120
    bool threaded;              // use threads or not
121
    bool isrunning;             // flag indicating whether a simulation run is ongoing
122
123
    int barrierMin;
124
125
  private:
126
    // internal
127
    void checkActive()  {if (getActiveSimulation()!=this) throw cRuntimeError(this, eWRONGSIM);}
128
129
  public:
130
    // internal: FES
131
#ifdef UNSAFE_FES
132
    cMessageHeap msgQueue;    // future messages (FES)
133
#else
134 93d0d4d3 Simon Tenbusch
    cLockedMessageHeap<cTTASLock> msgQueue;
135 01873262 Georg Kunz
#endif
136
137
    cMessageHeap& getMessageQueue() {return msgQueue;}  // accessor for sim_std.msg
138
139
    // Horizon thread pool
140
    cThreadPool* threadPool;
141
142
  private:
143
    /**
144
     * checks if the arrival module of this message is still alive. Return NULL
145
     * if not.
146
     */
147
    cSimpleModule* cleanDeadModule(cMessage* msg);
148
149
    /**
150
     * read configuration and setup the thread pool accordingly
151
     */
152
    void setupThreadPool();
153
154
  public:
155
    /** @name Constructor, destructor. */
156
    //@{
157
    /**
158
     * Constructor. The environment object will be associated with this simulation
159
     * object, and gets deleted in the simulation object's destructor.
160
     */
161
    cSimulation(const char *name, cEnvir *env);
162
163
    /**
164
     * Destructor.
165
     */
166
    virtual ~cSimulation();
167
    //@}
168
169
    /** @name Redefined cObject member functions. */
170
    //@{
171
    /**
172
     * Calls v->visit(this) for each contained object.
173
     * See cObject for more details.
174
     */
175
    virtual void forEachChild(cVisitor *v);
176
177
    /**
178
     * Redefined. (Reason: a C++ rule that overloaded virtual methods must be redefined together.)
179
     */
180
    virtual std::string getFullPath() const;
181
    //@}
182
183
    /** @name Accessing and switching the active simulation object */
184
    //@{
185
    /**
186
     * Returns the active simulation object. May be NULL.
187
     */
188
    static cSimulation *getActiveSimulation()  {return simPtr;}
189
190
    /**
191
     * Returns the environment object for the active simulation. Never returns NULL;
192
     * setActiveSimulation(NULL) will cause a static "do-nothing" instance to step in.
193
     */
194
    static cEnvir *getActiveEnvir()  {return evPtr;}
195
196
    /**
197
     * Activate the given simulation object, and its associated environment
198
     * object. NULL is also accepted; it will cause the static environment
199
     * object to step in (see getStaticEnvir()).
200
     */
201
    static void setActiveSimulation(cSimulation *sim);
202
203
    /**
204
     * Sets the environment object to use when there is no active simulation object.
205
     * The argument cannot be NULL.
206
     */
207
    static void setStaticEnvir(cEnvir *env);
208
209
    /**
210
     * Returns the environment object to use when there is no active simulation object.
211
     */
212
    static cEnvir *getStaticEnvir()  {return staticEvPtr;}
213
214
    /**
215
     * Returns the environment object associated with this simulation object.
216
     */
217
    cEnvir *getEnvir() const  {return ownEvPtr;}
218
    //@}
219
220
    /** @name Accessing modules. */
221
    //@{
222
223
    /**
224
     * Registers the module in cSimulation and assigns a module Id. It is called
225
     * internally during module creation. The Id of a deleted module is not
226
     * issued again to another module, because we want module Ids to be
227
     * unique during the whole simulation.
228
     */
229
    int registerModule(cModule *mod);
230
231
    /**
232
     * Deregisters the module from cSimulation. It is called internally from cModule
233
     * destructor.
234
     */
235
    void deregisterModule(cModule *mod);
236
237
    /**
238
     * Returns highest used module ID.
239
     */
240
    int getLastModuleId() const    {return last_id;}
241
242
    /**
243
     * Finds a module by its path. Inclusion of the name of the toplevel module
244
     * in the path is optional. Returns NULL if not found.
245
     */
246
    cModule *getModuleByPath(const char *modulepath) const;
247
248
    /**
249
     * Looks up a module by ID. If the module does not exist, returns NULL.
250
     */
251
    cModule *getModule(int id) const  {return id>=0 && id<size ? vect[id] : NULL;}
252
253
    /**
254
     * DEPRECATED because it might return null reference; use getModule(int) instead.
255
     *
256
     * Same as getModule(int), only this returns reference instead of pointer.
257
     */
258
    _OPPDEPRECATED cModule& operator[](int id) const  {return id>=0 && id<size ? *vect[id] : *(cModule *)NULL;}
259
260
    /**
261
     * Designates the system module, the top-level module in the model.
262
     */
263
    void setSystemModule(cModule *p);
264
265
    /**
266
     * Returns pointer to the system module, the top-level module in the model.
267
     */
268
    cModule *getSystemModule() const  {return systemmodp;}
269
    //@}
270
271
    /** @name Loading NED files.
272
     *
273
     * These functions delegate to the netbuilder part of the simulation kernel,
274
     * and they are present so that cEnvir and other libs outside the simkernel
275
     * do not need to directly depend on nedxml or netbuilder classes, and
276
     * conditional compilation (\#ifdef WITH_NETBUILDER) can be limited to the
277
     * simkernel.
278
     */
279
    //@{
280
281
    /**
282
     * Load all NED files from a NED source folder. This involves visiting
283
     * each subdirectory, and loading all "*.ned" files from there.
284
     * The given folder is assumed to be the root of the NED package hierarchy.
285
     * Returns the number of files loaded.
286
     *
287
     * Note: doneLoadingNedFiles() must be called after the last
288
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
289
     */
290
    static int loadNedSourceFolder(const char *foldername);
291
292
    /**
293
     * Load a single NED file. If the expected package is given (non-NULL),
294
     * it should match the package declaration inside the NED file.
295
     *
296
     * Note: doneLoadingNedFiles() must be called after the last
297
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
298
     */
299
    static void loadNedFile(const char *nedfname, const char *expectedPackage=NULL, bool isXML=false);
300
301
    /**
302
     * Parses and loads the NED source code passed in the nedtext argument.
303
     * The name argument will be used as filename in error messages, and
304
     * and should be unique among the files loaded. If the expected package
305
     * is given (non-NULL), it should match the package declaration inside
306
     * the NED file.
307
     *
308
     * Note: doneLoadingNedFiles() must be called after the last
309
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
310
     */
311
    static void loadNedText(const char *name, const char *nedtext, const char *expectedPackage=NULL, bool isXML=false);
312
313
    /**
314
     * To be called after all NED folders / files have been loaded
315
     * (see loadNedSourceFolder()/loadNedFile()/loadNedText()).
316
     * Issues errors for components that could not be fully resolved
317
     * because of missing base types or interfaces.
318
     */
319
    static void doneLoadingNedFiles();
320
321
    /**
322
     * Returns the NED package that corresponds to the given folder. Returns ""
323
     * for the default package, and "-" if the folder is outside all NED folders.
324
     */
325
    static std::string getNedPackageForFolder(const char *folder);
326
327
    /**
328
     * Discards all information loaded from NED files. This method may only be
329
     * called immediately before exiting, because cModuleType/cChannelType
330
     * objects may depend on the corresponding NED declarations being loaded.
331
     */
332
    static void clearLoadedNedFiles();
333
    //@}
334
335
    /** @name Setting up and finishing a simulation run. */
336
    //@{
337
338
    /**
339
     * Installs a scheduler object. This may only be called when no
340
     * network is set up. The cSimulation object will be responsible
341
     * for deallocating the scheduler object.
342
     */
343
    void setScheduler(cScheduler *scheduler);
344
345
    /**
346
     * Returns the scheduler object.
347
     */
348
    cScheduler *getScheduler() const  {return schedulerp;}
349
350
    /**
351
     * Builds a new network.
352
     */
353
    void setupNetwork(cModuleType *networkType);
354
355
    /**
356
     * Should be called after setupNetwork(), but before the first
357
     * doOneEvent() call. Includes initialization of the modules,
358
     * that is, invokes callInitialize() on the system module.
359
     */
360
    void startRun();
361
362
    /**
363
     * Recursively calls finish() on the modules of the network.
364
     * This method simply invokes callfinish() on the system module.
365
     */
366
    void callFinish();
367
368
    /**
369
     * Should be called at the end of a simulation run.
370
     */
371
    void endRun();
372
373
    /**
374
     * Cleans up the network currently set up. This involves deleting
375
     * all modules and deleting the messages in the scheduled-event list.
376
     */
377
    void deleteNetwork();
378
    //@}
379
380
    /** @name Information about the current simulation run. */
381
    //@{
382
    /**
383
     * Returns the current simulation stage: network building (CTX_BUILD),
384
     * network initialization (CTX_INIT), simulation execution (CTX_EVENT),
385
     * simulation finalization (CTX_FINISH), network cleanup (CTX_CLEANUP),
386
     * or other (CTX_NONE).
387
     */
388
    int getSimulationStage() const  {return simulationstage;}
389
390
    /**
391
     * Returns the cModuleType object that was instantiated to set up
392
     * the current simulation model.
393
     */
394
    cModuleType *getNetworkType() const  {return networktype;}
395
396
    /**
397
     * INTERNAL USE ONLY. This method should NEVER be invoked from
398
     * simulation models, only from scheduler classes subclassed from
399
     * cScheduler.
400
     */
401
    void setSimTime(simtime_t time) {cThreadPool::setSimTime(time);}
402
403
    /**
404
     * Returns the current simulation time. (It is also available via the
405
     * global simTime() function.)
406
     */
407
    simtime_t getSimTime() const  {return cThreadPool::getSimTime();}
408
409
    /**
410
     * Returns the sequence number of current event.
411
     */
412
    eventnumber_t getEventNumber() const  {return event_num;}
413
414
    /**
415
     * Is the simulation currently running.
416
     */
417
    bool isRunning() const {
418
        return isrunning;
419
    }
420
421
    /**
422
     * Returns the length of the initial warm-up period from the configuration.
423
     * Modules that compute and record scalar results manually (via recordScalar(),
424
     * recordStatistic(), etc.) should be implemented in a way that they ignore
425
     * observations generated during the warm-up period. cOutVector objects,
426
     * and results recorded via the signals mechanism automatically obey
427
     * the warm-up period and need not be modified. The warm-up period is useful
428
     * for steady-state simulations.
429
     */
430
    simtime_t_cref getWarmupPeriod() const  {return warmup_period;}
431
432
    /**
433
     * INTERNAL USE ONLY. Sets the warm-up period.
434
     */
435
    void setWarmupPeriod(simtime_t t)  {warmup_period = t;}
436
    //@}
437
438
    /** @name Scheduling and context switching during simulation. */
439
    //@{
440
441
    /**
442
     * The scheduler function. Returns the module to which the
443
     * next event (lowest timestamp event in the FES) belongs.
444
     *
445
     * If there is no more event (FES is empty), it throws cTerminationException.
446
     *
447
     * A NULL return value means that there is no error but execution
448
     * was stopped by the user (e.g. with STOP button on the GUI)
449
     * while selectNextModule() --or rather, the installed cScheduler object--
450
     * was waiting for external synchronization.
451
     */
452
    cSimpleModule *selectNextModule();
453
454
    /**
455
     * To be called between events from the environment of the simulation
456
     * (e.g. from Tkenv), this function returns a pointer to the event
457
     * at the head of the FES. It is only guaranteed to be the next event
458
     * with sequential simulation; with parallel, distributed or real-time
459
     * simulation there might be another event coming from other processes
460
     * with a yet smaller timestamp.
461
     *
462
     * This method is careful not to change anything. It never throws
463
     * an exception, and especially, it does NOT invoke the scheduler
464
     * (see cScheduler) because e.g. its parallel simulation incarnations
465
     * might do subtle things to keep events synchronized in various
466
     * partitions of the parallel simulation.
467
     */
468
    cMessage *guessNextEvent();
469
470
    /**
471
     * To be called between events from the environment of the simulation
472
     * (e.g. from Tkenv), this function returns the module associated
473
     * with the event at the head of the FES. It returns NULL if the
474
     * FES is empty, there is no module associated with the event, or
475
     * the module has already finished.
476
     *
477
     * Based on guessNextEvent(); see further comments there.
478
     */
479
    cSimpleModule *guessNextModule();
480
481
    /**
482
     * To be called between events from the environment of the simulation
483
     * (e.g. Tkenv), this function returns the simulation time of the event
484
     * at the head of the FES. In contrast, simTime() returns the time of the
485
     * last executed (or currently executing) event. Returns a negative value
486
     * if the FES is empty.
487
     *
488
     * Based on guessNextEvent(); see further comments there.
489
     */
490
    simtime_t guessNextSimtime();
491
492
    /**
493
     * Executes one event. The argument should be the module
494
     * returned by selectNextModule(); that is, the module
495
     * to which the next event (lowest timestamp event in
496
     * the FES) belongs. Also increments the event number
497
     * (returned by getEventNumber()).
498
     */
499 83ba5375 Simon Tenbusch
    void doOneEvent();
500 01873262 Georg Kunz
501
    /**
502
     * Switches to simple module's coroutine. This method is invoked
503
     * from doOneEvent() for activity()-based modules.
504
     */
505
    void transferTo(cSimpleModule *p);
506
507
    /**
508
     * Switches to main coroutine.
509
     */
510
    void transferToMain();
511
512
    /**
513
     * Inserts the given message into the future events queue while assigning
514
     * the current event to its scheduling event. Used internally by
515
     * cSimpleModule::scheduleAt() and various other cSimpleModule methods.
516
     */
517
    void insertMsg(cMessage *msg);
518
519
    /**
520
     * Sets the component (module or channel) in context. Used internally.
521
     */
522
    void setContext(cComponent *p);
523
524
    /**
525
     * Sets the context type (see CTX_xxx constants). Used internally.
526
     */
527
    void setContextType(int ctxtype)  {contexttype = ctxtype;}
528
529
    /**
530
     * Sets global context. Used internally.
531
     */
532
    void setGlobalContext()  {
533
        cThreadPool::setContext(NULL);
534
        cThreadPool::setDefaultOwner(&defaultList);
535
    }
536
    /**
537
     * Returns the module whose activity() method is currently active.
538
     * Returns NULL if no module is running, or the current module uses
539
     * handleMessage().
540
     */
541
    cSimpleModule *getActivityModule() const {return activitymodp;}
542
543
    /**
544
     * Returns the component (module or channel) currently in context.
545
     */
546
    cComponent *getContext() const {return cThreadPool::getContext();}
547
548
    /**
549
     * Returns value only valid if getContextModule()!=NULL. Returns one of:
550
     * CTX_BUILD, CTX_INITIALIZE, CTX_EVENT, CTX_FINISH, depending on
551
     * what the module in context is doing. In case of nested contexts
552
     * (e.g. when a module is dynamically created, initialized or manually
553
     * finalized during simulation), the innermost context type is returned.
554
     */
555
    int getContextType() const {return contexttype;}
556
557
    /**
558
     * If the current context is a module, returns its pointer,
559
     * otherwise returns NULL.
560
     */
561
    cModule *getContextModule() const;
562
563
    /**
564
     * Returns the module currently in context as a simple module.
565
     * If the module in context is not a simple module, returns NULL.
566
     * This is a convenience function which simply calls getContextModule().
567
     */
568
    cSimpleModule *getContextSimpleModule() const;
569
    //@}
570
571
    /** @name Miscellaneous. */
572
    //@{
573
    /**
574
     * This function is guaranteed to return a different integer every time
575
     * it is called (usually 0, 1, 2, ...). This method works with parallel
576
     * simulation as well, so it is recommended over incrementing a global
577
     * variable. Useful for generating unique network addresses, etc.
578
     */
579
    unsigned long getUniqueNumber();
580
581
    /**
582
     * Writes a snapshot of the given object and its children to the
583
     * textual snapshot file.
584
     * This method is called internally from cSimpleModule's snapshot().
585
     */
586
    bool snapshot(cObject *obj, const char *label);
587
588
    /**
589
     * Returns the object used for fingerprint calculation. It returns NULL
590
     * if no fingerprint is being calculated during this simulation run.
591
     */
592
    cHasher *getHasher() {return hasherp;}
593
594
    /**
595
     * Installs a new hasher object, used for fingerprint calculation.
596
     */
597
    void setHasher(cHasher *hasher);
598
    //@}
599
};
600
601
/**
602
 * Returns the current simulation time.
603
 */
604
inline simtime_t simTime() {return cSimulation::getActiveSimulation()->getSimTime();}
605
606
607
NAMESPACE_END
608
609
610
#endif