Statistics
| Branch: | Revision:

root / include / csimulation.h @ fbe00e73

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  cStopWatch;
57

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

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

    
67

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

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

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

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

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

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

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

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

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

    
126
    cStopWatch sequentialWatch;
127

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
625

    
626
};
627

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

    
633

    
634
NAMESPACE_END
635

    
636

    
637
#endif
638