Statistics
| Branch: | Revision:

root / include / csimulation.h @ 68da4f12

History | View | Annotate | Download (20.8 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 "cttaslock.h"
30
#include "cnolock.h"
31
#include "cpthreadlock.h"
32

    
33
#include "cthreadpool.h"
34
#include "cstopwatch.h"
35
#include "cscheduler.h"
36
#include <list>
37

    
38
NAMESPACE_BEGIN
39

    
40
//=== classes mentioned:
41
class  cMessage;
42
class  cGate;
43
class  cModule;
44
class  cSimpleModule;
45
class  cCompoundModule;
46
class  cSimulation;
47
class  cException;
48
class  cScheduler;
49
class  cParsimPartition;
50
class  cNEDFileLoader;
51
class  cHasher;
52
class  cModuleType;
53
class  cEnvir;
54
class  cDefaultList;
55
class  cThreadPool;
56
class  cAsyncModule;
57
class  cStopWatch;
58

    
59
SIM_API extern cDefaultList defaultList; // also in globals.h
60

    
61
/**
62
 * The active simulation manager instance.
63
 *
64
 * @ingroup SimCore
65
 */
66
#define simulation  (*cSimulation::getActiveSimulation())
67

    
68

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

    
91
  private:
92
    // global variables
93
    static cSimulation *simPtr; // the active cSimulation instance
94
    static cEnvir *evPtr;       // the active cEnvir instance
95
    static cEnvir *staticEvPtr; // the environment to activate when simPtr becomes NULL
96

    
97
    // variables of the module vector
98
    int size;                 // size of vector
99
    int delta;                // if needed, grows by delta
100
    cModule **vect;           // vector of modules, vect[0] is not used
101
    int last_id;              // index of last used pos. in vect[]
102

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

    
113
    int simulationstage;      // simulation stage (one of CTX_NONE, CTX_BUILD, CTX_EVENT, CTX_INITIALIZE, CTX_FINISH or CTX_CLEANUP)
114
    //simtime_t sim_time;       // simulation time (time of current event)
115
    eventnumber_t event_num;  // sequence number of current event
116

    
117
    cMessage *msg_for_activity; // helper variable to pass the received message into activity()
118
    cException *exception;    // helper variable to get exceptions back from activity()
119

    
120
    cHasher *hasherp;         // used for fingerprint calculation
121

    
122
    bool threaded;              // use threads or not
123
    bool isrunning;             // flag indicating whether a simulation run is ongoing
124

    
125
    unsigned int eventsPerSimTimeInstance; // count how many event occur at the same sim time
126

    
127
    cStopWatch sequentialWatch;
128

    
129
    bool endSimulation;     // used to signal shutdown from threaded context
130

    
131
  private:
132
    // internal
133
    void checkActive()  {if (getActiveSimulation()!=this) throw cRuntimeError(this, eWRONGSIM);}
134

    
135
  public:
136
    // internal: FES
137
#ifdef UNSAFE_FES
138
    cMessageHeap msgQueue;    // future messages (FES)
139
#else
140
    //
141
    // choose on of the following locks
142
    //
143
    // cLockedMessageHeap<cNoLock> msgQueue;
144
    // cLockedMessageHeap<cPThreadLock> msgQueue;
145
    cLockedMessageHeap<cTTASLock> msgQueue;
146
#endif
147

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

    
150
    // Horizon thread pool
151
    cThreadPool* threadPool;
152

    
153
  private:
154
    /**
155
     * checks if the arrival module of this message is still alive. Return NULL
156
     * if not.
157
     */
158
    cSimpleModule* cleanDeadModule(cMessage* msg);
159

    
160
    /**
161
     * read configuration and setup the thread pool accordingly
162
     */
163
    void setupThreadPool();
164

    
165
    /*
166
     * setup the local Random Number Generators for each cAsyncmodule
167
     */
168
    void setupLocalRNGs();
169

    
170
  public:
171
    /** @name Constructor, destructor. */
172
    //@{
173
    /**
174
     * Constructor. The environment object will be associated with this simulation
175
     * object, and gets deleted in the simulation object's destructor.
176
     */
177
    cSimulation(const char *name, cEnvir *env);
178

    
179
    /**
180
     * Destructor.
181
     */
182
    virtual ~cSimulation();
183
    //@}
184

    
185
    /** @name Redefined cObject member functions. */
186
    //@{
187
    /**
188
     * Calls v->visit(this) for each contained object.
189
     * See cObject for more details.
190
     */
191
    virtual void forEachChild(cVisitor *v);
192

    
193
    /**
194
     * Redefined. (Reason: a C++ rule that overloaded virtual methods must be redefined together.)
195
     */
196
    virtual std::string getFullPath() const;
197
    //@}
198

    
199
    /** @name Accessing and switching the active simulation object */
200
    //@{
201
    /**
202
     * Returns the active simulation object. May be NULL.
203
     */
204
    static cSimulation *getActiveSimulation()  {return simPtr;}
205

    
206
    /**
207
     * Returns the environment object for the active simulation. Never returns NULL;
208
     * setActiveSimulation(NULL) will cause a static "do-nothing" instance to step in.
209
     */
210
    static cEnvir *getActiveEnvir()  {return evPtr;}
211

    
212
    /**
213
     * Activate the given simulation object, and its associated environment
214
     * object. NULL is also accepted; it will cause the static environment
215
     * object to step in (see getStaticEnvir()).
216
     */
217
    static void setActiveSimulation(cSimulation *sim);
218

    
219
    /**
220
     * Sets the environment object to use when there is no active simulation object.
221
     * The argument cannot be NULL.
222
     */
223
    static void setStaticEnvir(cEnvir *env);
224

    
225
    /**
226
     * Returns the environment object to use when there is no active simulation object.
227
     */
228
    static cEnvir *getStaticEnvir()  {return staticEvPtr;}
229

    
230
    /**
231
     * Returns the environment object associated with this simulation object.
232
     */
233
    cEnvir *getEnvir() const  {return ownEvPtr;}
234
    //@}
235

    
236
    /** @name Accessing modules. */
237
    //@{
238

    
239
    /**
240
     * Registers the module in cSimulation and assigns a module Id. It is called
241
     * internally during module creation. The Id of a deleted module is not
242
     * issued again to another module, because we want module Ids to be
243
     * unique during the whole simulation.
244
     */
245
    int registerModule(cModule *mod);
246

    
247
    /**
248
     * Deregisters the module from cSimulation. It is called internally from cModule
249
     * destructor.
250
     */
251
    void deregisterModule(cModule *mod);
252

    
253
    /**
254
     * Returns highest used module ID.
255
     */
256
    int getLastModuleId() const    {return last_id;}
257

    
258
    /**
259
     * Finds a module by its path. Inclusion of the name of the toplevel module
260
     * in the path is optional. Returns NULL if not found.
261
     */
262
    cModule *getModuleByPath(const char *modulepath) const;
263

    
264
    /**
265
     * Looks up a module by ID. If the module does not exist, returns NULL.
266
     */
267
    cModule *getModule(int id) const  {return id>=0 && id<size ? vect[id] : NULL;}
268

    
269
    /**
270
     * DEPRECATED because it might return null reference; use getModule(int) instead.
271
     *
272
     * Same as getModule(int), only this returns reference instead of pointer.
273
     */
274
    _OPPDEPRECATED cModule& operator[](int id) const  {return id>=0 && id<size ? *vect[id] : *(cModule *)NULL;}
275

    
276
    /**
277
     * Designates the system module, the top-level module in the model.
278
     */
279
    void setSystemModule(cModule *p);
280

    
281
    /**
282
     * Returns pointer to the system module, the top-level module in the model.
283
     */
284
    cModule *getSystemModule() const  {return systemmodp;}
285
    //@}
286

    
287
    /** @name Loading NED files.
288
     *
289
     * These functions delegate to the netbuilder part of the simulation kernel,
290
     * and they are present so that cEnvir and other libs outside the simkernel
291
     * do not need to directly depend on nedxml or netbuilder classes, and
292
     * conditional compilation (\#ifdef WITH_NETBUILDER) can be limited to the
293
     * simkernel.
294
     */
295
    //@{
296

    
297
    /**
298
     * Load all NED files from a NED source folder. This involves visiting
299
     * each subdirectory, and loading all "*.ned" files from there.
300
     * The given folder is assumed to be the root of the NED package hierarchy.
301
     * Returns the number of files loaded.
302
     *
303
     * Note: doneLoadingNedFiles() must be called after the last
304
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
305
     */
306
    static int loadNedSourceFolder(const char *foldername);
307

    
308
    /**
309
     * Load a single NED file. If the expected package is given (non-NULL),
310
     * it should match the package declaration inside the NED file.
311
     *
312
     * Note: doneLoadingNedFiles() must be called after the last
313
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
314
     */
315
    static void loadNedFile(const char *nedfname, const char *expectedPackage=NULL, bool isXML=false);
316

    
317
    /**
318
     * Parses and loads the NED source code passed in the nedtext argument.
319
     * The name argument will be used as filename in error messages, and
320
     * and should be unique among the files loaded. If the expected package
321
     * is given (non-NULL), it should match the package declaration inside
322
     * the NED file.
323
     *
324
     * Note: doneLoadingNedFiles() must be called after the last
325
     * loadNedSourceFolder()/loadNedFile()/loadNedText() call.
326
     */
327
    static void loadNedText(const char *name, const char *nedtext, const char *expectedPackage=NULL, bool isXML=false);
328

    
329
    /**
330
     * To be called after all NED folders / files have been loaded
331
     * (see loadNedSourceFolder()/loadNedFile()/loadNedText()).
332
     * Issues errors for components that could not be fully resolved
333
     * because of missing base types or interfaces.
334
     */
335
    static void doneLoadingNedFiles();
336

    
337
    /**
338
     * Returns the NED package that corresponds to the given folder. Returns ""
339
     * for the default package, and "-" if the folder is outside all NED folders.
340
     */
341
    static std::string getNedPackageForFolder(const char *folder);
342

    
343
    /**
344
     * Discards all information loaded from NED files. This method may only be
345
     * called immediately before exiting, because cModuleType/cChannelType
346
     * objects may depend on the corresponding NED declarations being loaded.
347
     */
348
    static void clearLoadedNedFiles();
349
    //@}
350

    
351
    /** @name Setting up and finishing a simulation run. */
352
    //@{
353

    
354
    /**
355
     * Installs a scheduler object. This may only be called when no
356
     * network is set up. The cSimulation object will be responsible
357
     * for deallocating the scheduler object.
358
     */
359
    void setScheduler(cScheduler *scheduler);
360

    
361
    /**
362
     * Returns the scheduler object.
363
     */
364
    cScheduler *getScheduler() const  {return schedulerp;}
365

    
366
    /**
367
     * Builds a new network.
368
     */
369
    void setupNetwork(cModuleType *networkType);
370

    
371
    /**
372
     * Should be called after setupNetwork(), but before the first
373
     * doOneEvent() call. Includes initialization of the modules,
374
     * that is, invokes callInitialize() on the system module.
375
     */
376
    void startRun();
377

    
378
    /**
379
     * Recursively calls finish() on the modules of the network.
380
     * This method simply invokes callfinish() on the system module.
381
     */
382
    void callFinish();
383

    
384
    /**
385
     * Should be called at the end of a simulation run.
386
     */
387
    void endRun();
388

    
389
    /**
390
     * Cleans up the network currently set up. This involves deleting
391
     * all modules and deleting the messages in the scheduled-event list.
392
     */
393
    void deleteNetwork();
394

    
395
    /**
396
     * signal shutdown from thread
397
     */
398
    void signalShutdown()  { endSimulation = true; }
399
    //@}
400

    
401
    /** @name Information about the current simulation run. */
402
    //@{
403
    /**
404
     * Returns the current simulation stage: network building (CTX_BUILD),
405
     * network initialization (CTX_INIT), simulation execution (CTX_EVENT),
406
     * simulation finalization (CTX_FINISH), network cleanup (CTX_CLEANUP),
407
     * or other (CTX_NONE).
408
     */
409
    int getSimulationStage() const  {return simulationstage;}
410

    
411
    /**
412
     * Returns the cModuleType object that was instantiated to set up
413
     * the current simulation model.
414
     */
415
    cModuleType *getNetworkType() const  {return networktype;}
416

    
417
    /**
418
     * INTERNAL USE ONLY. This method should NEVER be invoked from
419
     * simulation models, only from scheduler classes subclassed from
420
     * cScheduler.
421
     */
422
    void setSimTime(simtime_t time) {cThreadPool::setSimTime(time);}
423

    
424
    /**
425
     * Returns the current simulation time. (It is also available via the
426
     * global simTime() function.)
427
     */
428
    simtime_t getSimTime() const  {return cThreadPool::getSimTime();}
429

    
430
    /**
431
     * Returns the sequence number of current event.
432
     */
433
    eventnumber_t getEventNumber() const  {return event_num;}
434

    
435
    /**
436
     * Is the simulation currently running.
437
     */
438
    bool isRunning() const {
439
        return isrunning;
440
    }
441

    
442
    /**
443
     * Returns the length of the initial warm-up period from the configuration.
444
     * Modules that compute and record scalar results manually (via recordScalar(),
445
     * recordStatistic(), etc.) should be implemented in a way that they ignore
446
     * observations generated during the warm-up period. cOutVector objects,
447
     * and results recorded via the signals mechanism automatically obey
448
     * the warm-up period and need not be modified. The warm-up period is useful
449
     * for steady-state simulations.
450
     */
451
    simtime_t_cref getWarmupPeriod() const  {return warmup_period;}
452

    
453
    /**
454
     * INTERNAL USE ONLY. Sets the warm-up period.
455
     */
456
    void setWarmupPeriod(simtime_t t)  {warmup_period = t;}
457
    //@}
458

    
459
    /** @name Scheduling and context switching during simulation. */
460
    //@{
461

    
462
    /**
463
     * The scheduler function. Returns the module to which the
464
     * next event (lowest timestamp event in the FES) belongs.
465
     *
466
     * If there is no more event (FES is empty), it throws cTerminationException.
467
     *
468
     * A NULL return value means that there is no error but execution
469
     * was stopped by the user (e.g. with STOP button on the GUI)
470
     * while selectNextModule() --or rather, the installed cScheduler object--
471
     * was waiting for external synchronization.
472
     */
473
    cSimpleModule *selectNextModule();
474

    
475
    /**
476
     * To be called between events from the environment of the simulation
477
     * (e.g. from Tkenv), this function returns a pointer to the event
478
     * at the head of the FES. It is only guaranteed to be the next event
479
     * with sequential simulation; with parallel, distributed or real-time
480
     * simulation there might be another event coming from other processes
481
     * with a yet smaller timestamp.
482
     *
483
     * This method is careful not to change anything. It never throws
484
     * an exception, and especially, it does NOT invoke the scheduler
485
     * (see cScheduler) because e.g. its parallel simulation incarnations
486
     * might do subtle things to keep events synchronized in various
487
     * partitions of the parallel simulation.
488
     */
489
    cMessage *guessNextEvent();
490

    
491
    /**
492
     * To be called between events from the environment of the simulation
493
     * (e.g. from Tkenv), this function returns the module associated
494
     * with the event at the head of the FES. It returns NULL if the
495
     * FES is empty, there is no module associated with the event, or
496
     * the module has already finished.
497
     *
498
     * Based on guessNextEvent(); see further comments there.
499
     */
500
    cSimpleModule *guessNextModule();
501

    
502
    /**
503
     * To be called between events from the environment of the simulation
504
     * (e.g. Tkenv), this function returns the simulation time of the event
505
     * at the head of the FES. In contrast, simTime() returns the time of the
506
     * last executed (or currently executing) event. Returns a negative value
507
     * if the FES is empty.
508
     *
509
     * Based on guessNextEvent(); see further comments there.
510
     */
511
    simtime_t guessNextSimtime();
512

    
513
    /**
514
     * Executes one event. The argument should be the module
515
     * returned by selectNextModule(); that is, the module
516
     * to which the next event (lowest timestamp event in
517
     * the FES) belongs. Also increments the event number
518
     * (returned by getEventNumber()).
519
     */
520
    void doOneEvent(cMessage* msg);
521

    
522
    /**
523
     * Switches to simple module's coroutine. This method is invoked
524
     * from doOneEvent() for activity()-based modules.
525
     */
526
    void transferTo(cSimpleModule *p);
527

    
528
    /**
529
     * Switches to main coroutine.
530
     */
531
    void transferToMain();
532

    
533
    /**
534
     * Inserts the given message into the future events queue while assigning
535
     * the current event to its scheduling event. Used internally by
536
     * cSimpleModule::scheduleAt() and various other cSimpleModule methods.
537
     */
538
    void insertMsg(cMessage *msg);
539

    
540
    /**
541
     * Sets the component (module or channel) in context. Used internally.
542
     */
543
    void setContext(cComponent *p);
544

    
545
    /**
546
     * Sets the context type (see CTX_xxx constants). Used internally.
547
     */
548
    void setContextType(int ctxtype)  {contexttype = ctxtype;}
549

    
550
    /**
551
     * Sets global context. Used internally.
552
     */
553
    void setGlobalContext()  {
554
        cThreadPool::setContext(NULL);
555
        cThreadPool::setDefaultOwner(&defaultList);
556
    }
557
    /**
558
     * Returns the module whose activity() method is currently active.
559
     * Returns NULL if no module is running, or the current module uses
560
     * handleMessage().
561
     */
562
    cSimpleModule *getActivityModule() const {return activitymodp;}
563

    
564
    /**
565
     * Returns the component (module or channel) currently in context.
566
     */
567
    cComponent *getContext() const {return cThreadPool::getContext();}
568

    
569
    /**
570
     * Returns value only valid if getContextModule()!=NULL. Returns one of:
571
     * CTX_BUILD, CTX_INITIALIZE, CTX_EVENT, CTX_FINISH, depending on
572
     * what the module in context is doing. In case of nested contexts
573
     * (e.g. when a module is dynamically created, initialized or manually
574
     * finalized during simulation), the innermost context type is returned.
575
     */
576
    int getContextType() const {return contexttype;}
577

    
578
    /**
579
     * If the current context is a module, returns its pointer,
580
     * otherwise returns NULL.
581
     */
582
    cModule *getContextModule() const;
583

    
584
    /**
585
     * Returns the module currently in context as a simple module.
586
     * If the module in context is not a simple module, returns NULL.
587
     * This is a convenience function which simply calls getContextModule().
588
     */
589
    cSimpleModule *getContextSimpleModule() const;
590
    //@}
591

    
592
    /** @name Miscellaneous. */
593
    //@{
594
    /**
595
     * This function is guaranteed to return a different integer every time
596
     * it is called (usually 0, 1, 2, ...). This method works with parallel
597
     * simulation as well, so it is recommended over incrementing a global
598
     * variable. Useful for generating unique network addresses, etc.
599
     */
600
    unsigned long getUniqueNumber();
601

    
602
    /**
603
     * Writes a snapshot of the given object and its children to the
604
     * textual snapshot file.
605
     * This method is called internally from cSimpleModule's snapshot().
606
     */
607
    bool snapshot(cObject *obj, const char *label);
608

    
609
    /**
610
     * Returns the object used for fingerprint calculation. It returns NULL
611
     * if no fingerprint is being calculated during this simulation run.
612
     */
613
    cHasher *getHasher() {return hasherp;}
614

    
615
    /**
616
     * Installs a new hasher object, used for fingerprint calculation.
617
     */
618
    void setHasher(cHasher *hasher);
619

    
620
    /*
621
     * returns next execution order Id of given msg
622
     */
623
    unsigned int getNextExecutionOrderId(cMessage* msg);
624
    //@}
625

    
626

    
627
};
628

    
629
/**
630
 * Returns the current simulation time.
631
 */
632
inline simtime_t simTime() {return cSimulation::getActiveSimulation()->getSimTime();}
633

    
634

    
635
NAMESPACE_END
636

    
637

    
638
#endif
639