Statistics
| Branch: | Revision:

root / include / csimulation.h @ 01873262

History | View | Annotate | Download (20.1 KB)

1
//==========================================================================
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
#include "cspinlockedmsgheap.h"
30
#include "cthreadpool.h"
31
#include "cstopwatch.h"
32
#include <list>
33

    
34
NAMESPACE_BEGIN
35

    
36
//=== classes mentioned:
37
class  cMessage;
38
class  cGate;
39
class  cModule;
40
class  cSimpleModule;
41
class  cCompoundModule;
42
class  cSimulation;
43
class  cException;
44
class  cScheduler;
45
class  cParsimPartition;
46
class  cNEDFileLoader;
47
class  cHasher;
48
class  cModuleType;
49
class  cEnvir;
50
class  cDefaultList;
51
class  cThreadPool;
52
class  cAsyncModule;
53

    
54
SIM_API extern cDefaultList defaultList; // also in globals.h
55

    
56
/**
57
 * The active simulation manager instance.
58
 *
59
 * @ingroup SimCore
60
 */
61
#define simulation  (*cSimulation::getActiveSimulation())
62

    
63

    
64
/**
65
 * Simulation manager class.  cSimulation is the central class in \opp.
66
 * It stores the active simulation model, and provides methods for setting up,
67
 * running and finalizing simulations.
68
 *
69
 * Most cSimulation methods are not of interest for simulation model code,
70
 * they are used internally (e.g. by the user interface libraries (Envir,
71
 * Cmdenv, Tkenv) to set up and run simulations).
72
 *
73
 * Some methods which can be of interest when programming simple modules:
74
 * getUniqueNumber(), getModuleByPath(), getModule(), snapshot().
75
 *
76
 * @ingroup SimCore
77
 * @ingroup Internals
78
 */
79
class SIM_API cSimulation : public cNamedObject, noncopyable
80
{
81
    friend class cSimpleModule;
82
    friend class cThreadPool;
83
    friend class cLockedThreadPool;
84
    friend class cSpinningThreadPool;
85

    
86
  private:
87
    // global variables
88
    static cSimulation *simPtr; // the active cSimulation instance
89
    static cEnvir *evPtr;       // the active cEnvir instance
90
    static cEnvir *staticEvPtr; // the environment to activate when simPtr becomes NULL
91

    
92
    // variables of the module vector
93
    int size;                 // size of vector
94
    int delta;                // if needed, grows by delta
95
    cModule **vect;           // vector of modules, vect[0] is not used
96
    int last_id;              // index of last used pos. in vect[]
97

    
98
    // simulation vars
99
    cEnvir *ownEvPtr;         // the environment that belongs to this simulation object
100
    cModule *systemmodp;      // pointer to system (root) module
101
    cSimpleModule *activitymodp; // the module currently executing activity() (NULL if handleMessage() or in main)
102
    //cComponent *contextmodp;  // component in context (or NULL)
103
    int contexttype;          // the innermost context type (one of CTX_BUILD, CTX_EVENT, CTX_INITIALIZE, CTX_FINISH)
104
    cModuleType *networktype; // network type
105
    cScheduler *schedulerp;   // event scheduler
106
    simtime_t warmup_period;  // warm-up period
107

    
108
    int simulationstage;      // simulation stage (one of CTX_NONE, CTX_BUILD, CTX_EVENT, CTX_INITIALIZE, CTX_FINISH or CTX_CLEANUP)
109
    //simtime_t sim_time;       // simulation time (time of current event)
110
    eventnumber_t event_num;  // sequence number of current event
111

    
112
    cMessage *msg_for_activity; // helper variable to pass the received message into activity()
113
    cException *exception;    // helper variable to get exceptions back from activity()
114

    
115
    cHasher *hasherp;         // used for fingerprint calculation
116

    
117
    bool threaded;              // use threads or not
118
    bool isrunning;             // flag indicating whether a simulation run is ongoing
119

    
120
    int barrierMin;
121

    
122
  private:
123
    // internal
124
    void checkActive()  {if (getActiveSimulation()!=this) throw cRuntimeError(this, eWRONGSIM);}
125

    
126
  public:
127
    // internal: FES
128
#ifdef UNSAFE_FES
129
    cMessageHeap msgQueue;    // future messages (FES)
130
#else
131
    //    cLockedMessageHeap msgQueue;
132
    cSpinlockedMessageHeap msgQueue;
133
#endif
134

    
135
    cMessageHeap& getMessageQueue() {return msgQueue;}  // accessor for sim_std.msg
136

    
137
    // Horizon thread pool
138
    cThreadPool* threadPool;
139

    
140
  private:
141
    /**
142
     * checks if the arrival module of this message is still alive. Return NULL
143
     * if not.
144
     */
145
    cSimpleModule* cleanDeadModule(cMessage* msg);
146

    
147
    /**
148
     * read configuration and setup the thread pool accordingly
149
     */
150
    void setupThreadPool();
151

    
152
  public:
153
    /** @name Constructor, destructor. */
154
    //@{
155
    /**
156
     * Constructor. The environment object will be associated with this simulation
157
     * object, and gets deleted in the simulation object's destructor.
158
     */
159
    cSimulation(const char *name, cEnvir *env);
160

    
161
    /**
162
     * Destructor.
163
     */
164
    virtual ~cSimulation();
165
    //@}
166

    
167
    /** @name Redefined cObject member functions. */
168
    //@{
169
    /**
170
     * Calls v->visit(this) for each contained object.
171
     * See cObject for more details.
172
     */
173
    virtual void forEachChild(cVisitor *v);
174

    
175
    /**
176
     * Redefined. (Reason: a C++ rule that overloaded virtual methods must be redefined together.)
177
     */
178
    virtual std::string getFullPath() const;
179
    //@}
180

    
181
    /** @name Accessing and switching the active simulation object */
182
    //@{
183
    /**
184
     * Returns the active simulation object. May be NULL.
185
     */
186
    static cSimulation *getActiveSimulation()  {return simPtr;}
187

    
188
    /**
189
     * Returns the environment object for the active simulation. Never returns NULL;
190
     * setActiveSimulation(NULL) will cause a static "do-nothing" instance to step in.
191
     */
192
    static cEnvir *getActiveEnvir()  {return evPtr;}
193

    
194
    /**
195
     * Activate the given simulation object, and its associated environment
196
     * object. NULL is also accepted; it will cause the static environment
197
     * object to step in (see getStaticEnvir()).
198
     */
199
    static void setActiveSimulation(cSimulation *sim);
200

    
201
    /**
202
     * Sets the environment object to use when there is no active simulation object.
203
     * The argument cannot be NULL.
204
     */
205
    static void setStaticEnvir(cEnvir *env);
206

    
207
    /**
208
     * Returns the environment object to use when there is no active simulation object.
209
     */
210
    static cEnvir *getStaticEnvir()  {return staticEvPtr;}
211

    
212
    /**
213
     * Returns the environment object associated with this simulation object.
214
     */
215
    cEnvir *getEnvir() const  {return ownEvPtr;}
216
    //@}
217

    
218
    /** @name Accessing modules. */
219
    //@{
220

    
221
    /**
222
     * Registers the module in cSimulation and assigns a module Id. It is called
223
     * internally during module creation. The Id of a deleted module is not
224
     * issued again to another module, because we want module Ids to be
225
     * unique during the whole simulation.
226
     */
227
    int registerModule(cModule *mod);
228

    
229
    /**
230
     * Deregisters the module from cSimulation. It is called internally from cModule
231
     * destructor.
232
     */
233
    void deregisterModule(cModule *mod);
234

    
235
    /**
236
     * Returns highest used module ID.
237
     */
238
    int getLastModuleId() const    {return last_id;}
239

    
240
    /**
241
     * Finds a module by its path. Inclusion of the name of the toplevel module
242
     * in the path is optional. Returns NULL if not found.
243
     */
244
    cModule *getModuleByPath(const char *modulepath) const;
245

    
246
    /**
247
     * Looks up a module by ID. If the module does not exist, returns NULL.
248
     */
249
    cModule *getModule(int id) const  {return id>=0 && id<size ? vect[id] : NULL;}
250

    
251
    /**
252
     * DEPRECATED because it might return null reference; use getModule(int) instead.
253
     *
254
     * Same as getModule(int), only this returns reference instead of pointer.
255
     */
256
    _OPPDEPRECATED cModule& operator[](int id) const  {return id>=0 && id<size ? *vect[id] : *(cModule *)NULL;}
257

    
258
    /**
259
     * Designates the system module, the top-level module in the model.
260
     */
261
    void setSystemModule(cModule *p);
262

    
263
    /**
264
     * Returns pointer to the system module, the top-level module in the model.
265
     */
266
    cModule *getSystemModule() const  {return systemmodp;}
267
    //@}
268

    
269
    /** @name Loading NED files.
270
     *
271
     * These functions delegate to the netbuilder part of the simulation kernel,
272
     * and they are present so that cEnvir and other libs outside the simkernel
273
     * do not need to directly depend on nedxml or netbuilder classes, and
274
     * conditional compilation (\#ifdef WITH_NETBUILDER) can be limited to the
275
     * simkernel.
276
     */
277
    //@{
278

    
279
    /**
280
     * Load all NED files from a NED source folder. This involves visiting
281
     * each subdirectory, and loading all "*.ned" files from there.
282
     * The given folder is assumed to be the root of the NED package hierarchy.
283
     * Returns the number of files loaded.
284
     *
285
     * Note: doneLoadingNedFiles() must be called after the last
286
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
287
     */
288
    static int loadNedSourceFolder(const char *foldername);
289

    
290
    /**
291
     * Load a single NED file. If the expected package is given (non-NULL),
292
     * it should match the package declaration inside the NED file.
293
     *
294
     * Note: doneLoadingNedFiles() must be called after the last
295
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
296
     */
297
    static void loadNedFile(const char *nedfname, const char *expectedPackage=NULL, bool isXML=false);
298

    
299
    /**
300
     * Parses and loads the NED source code passed in the nedtext argument.
301
     * The name argument will be used as filename in error messages, and
302
     * and should be unique among the files loaded. If the expected package
303
     * is given (non-NULL), it should match the package declaration inside
304
     * the NED file.
305
     *
306
     * Note: doneLoadingNedFiles() must be called after the last
307
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
308
     */
309
    static void loadNedText(const char *name, const char *nedtext, const char *expectedPackage=NULL, bool isXML=false);
310

    
311
    /**
312
     * To be called after all NED folders / files have been loaded
313
     * (see loadNedSourceFolder()/loadNedFile()/loadNedText()).
314
     * Issues errors for components that could not be fully resolved
315
     * because of missing base types or interfaces.
316
     */
317
    static void doneLoadingNedFiles();
318

    
319
    /**
320
     * Returns the NED package that corresponds to the given folder. Returns ""
321
     * for the default package, and "-" if the folder is outside all NED folders.
322
     */
323
    static std::string getNedPackageForFolder(const char *folder);
324

    
325
    /**
326
     * Discards all information loaded from NED files. This method may only be
327
     * called immediately before exiting, because cModuleType/cChannelType
328
     * objects may depend on the corresponding NED declarations being loaded.
329
     */
330
    static void clearLoadedNedFiles();
331
    //@}
332

    
333
    /** @name Setting up and finishing a simulation run. */
334
    //@{
335

    
336
    /**
337
     * Installs a scheduler object. This may only be called when no
338
     * network is set up. The cSimulation object will be responsible
339
     * for deallocating the scheduler object.
340
     */
341
    void setScheduler(cScheduler *scheduler);
342

    
343
    /**
344
     * Returns the scheduler object.
345
     */
346
    cScheduler *getScheduler() const  {return schedulerp;}
347

    
348
    /**
349
     * Builds a new network.
350
     */
351
    void setupNetwork(cModuleType *networkType);
352

    
353
    /**
354
     * Should be called after setupNetwork(), but before the first
355
     * doOneEvent() call. Includes initialization of the modules,
356
     * that is, invokes callInitialize() on the system module.
357
     */
358
    void startRun();
359

    
360
    /**
361
     * Recursively calls finish() on the modules of the network.
362
     * This method simply invokes callfinish() on the system module.
363
     */
364
    void callFinish();
365

    
366
    /**
367
     * Should be called at the end of a simulation run.
368
     */
369
    void endRun();
370

    
371
    /**
372
     * Cleans up the network currently set up. This involves deleting
373
     * all modules and deleting the messages in the scheduled-event list.
374
     */
375
    void deleteNetwork();
376
    //@}
377

    
378
    /** @name Information about the current simulation run. */
379
    //@{
380
    /**
381
     * Returns the current simulation stage: network building (CTX_BUILD),
382
     * network initialization (CTX_INIT), simulation execution (CTX_EVENT),
383
     * simulation finalization (CTX_FINISH), network cleanup (CTX_CLEANUP),
384
     * or other (CTX_NONE).
385
     */
386
    int getSimulationStage() const  {return simulationstage;}
387

    
388
    /**
389
     * Returns the cModuleType object that was instantiated to set up
390
     * the current simulation model.
391
     */
392
    cModuleType *getNetworkType() const  {return networktype;}
393

    
394
    /**
395
     * INTERNAL USE ONLY. This method should NEVER be invoked from
396
     * simulation models, only from scheduler classes subclassed from
397
     * cScheduler.
398
     */
399
    void setSimTime(simtime_t time) {cThreadPool::setSimTime(time);}
400

    
401
    /**
402
     * Returns the current simulation time. (It is also available via the
403
     * global simTime() function.)
404
     */
405
    simtime_t getSimTime() const  {return cThreadPool::getSimTime();}
406

    
407
    /**
408
     * Returns the sequence number of current event.
409
     */
410
    eventnumber_t getEventNumber() const  {return event_num;}
411

    
412
    /**
413
     * Is the simulation currently running.
414
     */
415
    bool isRunning() const {
416
        return isrunning;
417
    }
418

    
419
    /**
420
     * Returns the length of the initial warm-up period from the configuration.
421
     * Modules that compute and record scalar results manually (via recordScalar(),
422
     * recordStatistic(), etc.) should be implemented in a way that they ignore
423
     * observations generated during the warm-up period. cOutVector objects,
424
     * and results recorded via the signals mechanism automatically obey
425
     * the warm-up period and need not be modified. The warm-up period is useful
426
     * for steady-state simulations.
427
     */
428
    simtime_t_cref getWarmupPeriod() const  {return warmup_period;}
429

    
430
    /**
431
     * INTERNAL USE ONLY. Sets the warm-up period.
432
     */
433
    void setWarmupPeriod(simtime_t t)  {warmup_period = t;}
434
    //@}
435

    
436
    /** @name Scheduling and context switching during simulation. */
437
    //@{
438

    
439
    /**
440
     * The scheduler function. Returns the module to which the
441
     * next event (lowest timestamp event in the FES) belongs.
442
     *
443
     * If there is no more event (FES is empty), it throws cTerminationException.
444
     *
445
     * A NULL return value means that there is no error but execution
446
     * was stopped by the user (e.g. with STOP button on the GUI)
447
     * while selectNextModule() --or rather, the installed cScheduler object--
448
     * was waiting for external synchronization.
449
     */
450
    cSimpleModule *selectNextModule();
451

    
452
    /**
453
     * To be called between events from the environment of the simulation
454
     * (e.g. from Tkenv), this function returns a pointer to the event
455
     * at the head of the FES. It is only guaranteed to be the next event
456
     * with sequential simulation; with parallel, distributed or real-time
457
     * simulation there might be another event coming from other processes
458
     * with a yet smaller timestamp.
459
     *
460
     * This method is careful not to change anything. It never throws
461
     * an exception, and especially, it does NOT invoke the scheduler
462
     * (see cScheduler) because e.g. its parallel simulation incarnations
463
     * might do subtle things to keep events synchronized in various
464
     * partitions of the parallel simulation.
465
     */
466
    cMessage *guessNextEvent();
467

    
468
    /**
469
     * To be called between events from the environment of the simulation
470
     * (e.g. from Tkenv), this function returns the module associated
471
     * with the event at the head of the FES. It returns NULL if the
472
     * FES is empty, there is no module associated with the event, or
473
     * the module has already finished.
474
     *
475
     * Based on guessNextEvent(); see further comments there.
476
     */
477
    cSimpleModule *guessNextModule();
478

    
479
    /**
480
     * To be called between events from the environment of the simulation
481
     * (e.g. Tkenv), this function returns the simulation time of the event
482
     * at the head of the FES. In contrast, simTime() returns the time of the
483
     * last executed (or currently executing) event. Returns a negative value
484
     * if the FES is empty.
485
     *
486
     * Based on guessNextEvent(); see further comments there.
487
     */
488
    simtime_t guessNextSimtime();
489

    
490
    /**
491
     * Executes one event. The argument should be the module
492
     * returned by selectNextModule(); that is, the module
493
     * to which the next event (lowest timestamp event in
494
     * the FES) belongs. Also increments the event number
495
     * (returned by getEventNumber()).
496
     */
497
    void doOneEvent(cSimpleModule *m);
498

    
499
    /**
500
     * Switches to simple module's coroutine. This method is invoked
501
     * from doOneEvent() for activity()-based modules.
502
     */
503
    void transferTo(cSimpleModule *p);
504

    
505
    /**
506
     * Switches to main coroutine.
507
     */
508
    void transferToMain();
509

    
510
    /**
511
     * Inserts the given message into the future events queue while assigning
512
     * the current event to its scheduling event. Used internally by
513
     * cSimpleModule::scheduleAt() and various other cSimpleModule methods.
514
     */
515
    void insertMsg(cMessage *msg);
516

    
517
    /**
518
     * Sets the component (module or channel) in context. Used internally.
519
     */
520
    void setContext(cComponent *p);
521

    
522
    /**
523
     * Sets the context type (see CTX_xxx constants). Used internally.
524
     */
525
    void setContextType(int ctxtype)  {contexttype = ctxtype;}
526

    
527
    /**
528
     * Sets global context. Used internally.
529
     */
530
    void setGlobalContext()  {
531
        cThreadPool::setContext(NULL);
532
        cThreadPool::setDefaultOwner(&defaultList);
533
    }
534
    /**
535
     * Returns the module whose activity() method is currently active.
536
     * Returns NULL if no module is running, or the current module uses
537
     * handleMessage().
538
     */
539
    cSimpleModule *getActivityModule() const {return activitymodp;}
540

    
541
    /**
542
     * Returns the component (module or channel) currently in context.
543
     */
544
    cComponent *getContext() const {return cThreadPool::getContext();}
545

    
546
    /**
547
     * Returns value only valid if getContextModule()!=NULL. Returns one of:
548
     * CTX_BUILD, CTX_INITIALIZE, CTX_EVENT, CTX_FINISH, depending on
549
     * what the module in context is doing. In case of nested contexts
550
     * (e.g. when a module is dynamically created, initialized or manually
551
     * finalized during simulation), the innermost context type is returned.
552
     */
553
    int getContextType() const {return contexttype;}
554

    
555
    /**
556
     * If the current context is a module, returns its pointer,
557
     * otherwise returns NULL.
558
     */
559
    cModule *getContextModule() const;
560

    
561
    /**
562
     * Returns the module currently in context as a simple module.
563
     * If the module in context is not a simple module, returns NULL.
564
     * This is a convenience function which simply calls getContextModule().
565
     */
566
    cSimpleModule *getContextSimpleModule() const;
567
    //@}
568

    
569
    /** @name Miscellaneous. */
570
    //@{
571
    /**
572
     * This function is guaranteed to return a different integer every time
573
     * it is called (usually 0, 1, 2, ...). This method works with parallel
574
     * simulation as well, so it is recommended over incrementing a global
575
     * variable. Useful for generating unique network addresses, etc.
576
     */
577
    unsigned long getUniqueNumber();
578

    
579
    /**
580
     * Writes a snapshot of the given object and its children to the
581
     * textual snapshot file.
582
     * This method is called internally from cSimpleModule's snapshot().
583
     */
584
    bool snapshot(cObject *obj, const char *label);
585

    
586
    /**
587
     * Returns the object used for fingerprint calculation. It returns NULL
588
     * if no fingerprint is being calculated during this simulation run.
589
     */
590
    cHasher *getHasher() {return hasherp;}
591

    
592
    /**
593
     * Installs a new hasher object, used for fingerprint calculation.
594
     */
595
    void setHasher(cHasher *hasher);
596
    //@}
597
};
598

    
599
/**
600
 * Returns the current simulation time.
601
 */
602
inline simtime_t simTime() {return cSimulation::getActiveSimulation()->getSimTime();}
603

    
604

    
605
NAMESPACE_END
606

    
607

    
608
#endif
609