Statistics
| Branch: | Revision:

root / include / cenvir.h @ fbe00e73

History | View | Annotate | Download (24.4 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  CENVIR.H - part of
3
//
4
//                     OMNeT++/OMNEST
5
//            Discrete System Simulation in C++
6
//
7
//==========================================================================
8
9
/*--------------------------------------------------------------*
10
  Copyright (C) 1992-2008 Andras Varga
11
  Copyright (C) 2006-2008 OpenSim Ltd.
12

13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16
17
#ifndef __CENVIR_H
18
#define __CENVIR_H
19
20
#include <sstream>
21
#include <iostream>
22
#include "simkerneldefs.h"
23
#include "simtime_t.h"
24
#include "opp_string.h"
25
#include "csimulation.h"
26
27
NAMESPACE_BEGIN
28
29
class cObject;
30
class cOwnedObject;
31
class cMessage;
32
class cPar;
33
class cGate;
34
class cComponent;
35
class cModule;
36
class cSimpleModule;
37
class cStatistic;
38
class cRNG;
39
class cXMLElement;
40
class cEnvir;
41
class cConfiguration;
42
class cConfigurationEx;
43
44
using std::endl;
45
46
// internal macro, usage: EVCB.beginSend(...)
47
#define EVCB  ev.suppress_notifications ? (void)0 : ev
48
49
/**
50
 * Represents the "environment" or user interface of the simulation.
51
 *
52
 * Most common usage from model code (simple modules) is to write log
53
 * messages, e.g.:
54
 *
55
 * <pre>
56
 * ev << "Received packet " << msg->getName() << ", length " << msg->getBitLength()/8 << " bytes\n";
57
 * ev << "Sending up to higher layer\n";
58
 * </pre>
59
 *
60
 * Other useful methods are cEnvir::isGUI() and cEnvir::isDisabled().
61
 *
62
 * The rest of cEnvir methods are used internally for communication between
63
 * the simulation kernel and the environment.
64
 *
65
 * @ingroup Envir
66
 */
67
#define ev  (*cSimulation::getActiveEnvir())
68
69
70
/**
71
 * <tt>EV&lt;&lt;</tt> can be used instead of <tt>ev&lt;&lt;</tt> to make
72
 * logging more efficient. An example:
73
 * <pre>
74
 * EV << "Packet " << msg->getName() << " received\n";
75
 * </pre>
76
 *
77
 * <tt>EV</tt> utilizes cEnvir::isDisabled() to check whether the logged text
78
 * is going to be printed/stored anywhere, or just gets discarded; in the
79
 * latter case the <tt>&lt;&lt;</tt> operators do not get evaluated at all,
80
 * making the log statement effectively a zero cost operation.
81
 *
82
 * @ingroup Envir
83
 */
84
#define EV  ev.isDisabled()?ev:ev   /*Note: deliberately NO parens*/
85
86
87
/**
88
 * cEnvir represents the "environment" of the simulation. cEnvir
89
 * is a common facade for the Cmdenv and Tkenv user interfaces (and any
90
 * other future user interface). The cEnvir object can be accessed
91
 * via cSimulation::getActiveEnvir() or the ev macro.
92
 *
93
 * The default implementation of cEnvir can be customized by subclassing
94
 * the classes declared in the envirext.h header (e.g. cConfiguration,
95
 * cRNG, cOutputVectorManager, cOutputScalarManager), and selecting the
96
 * new classes from <tt>omnetpp.ini</tt>.
97
 *
98
 * @ingroup Envir
99
 * @ingroup EnvirExtensions
100
 */
101
class SIM_API cEnvir
102
{
103
    friend class evbuf;
104
  public:
105
    // Internal flag for express mode.
106
    bool disable_tracing;
107
108
    // Indicates whether eventlog recording is currently enabled
109
    bool record_eventlog;
110
111
    // Internal flag. When set to true, the simulation kernel MAY omit calling
112
    // the following cEnvir methods: messageScheduled(), messageCancelled(),
113
    // beginSend(), messageSendDirect(), messageSendHop(), messageSendHop(),
114
    // messageSendHop(), messageDeleted(), moduleReparented(), simulationEvent(),
115
    // componentMethodBegin(), moduleCreated(), moduleDeleted(), connectionCreated(),
116
    // connectionDeleted(), displayStringChanged().
117
    bool suppress_notifications;
118
119
    // Internal flag. When set, cRuntimeError constructor to raises an exception.
120
    bool debug_on_errors;
121
122
  protected:
123
    // further internal vars
124
    std::ostream out;
125
126
  protected:
127
    // internal: ev.printf() and ev<< eventually ends up here; write the first n characters of string s
128
    virtual void sputn(const char *s, int n) = 0;
129
130
    // internal: pop up a dialog with the given message; called from printfmsg()
131
    virtual void putsmsg(const char *msg) = 0;
132
133
    // internal: ask a yes/no question, throws exception if cancelled; askYesNo() delegates here
134
    virtual bool askyesno(const char *msg) = 0;
135
136
    // internal: flushes the internal stream buffer by terminating last line if needed
137
    void flushLastLine();
138
139
  public:
140
    /** @name Constructor, destructor. */
141
    //@{
142
143
    /**
144
     * Constructor.
145
     */
146
    cEnvir();
147
148
    /**
149
     * Destructor.
150
     */
151
    virtual ~cEnvir();
152
    //@}
153
154
    /** @name Methods to be called by the simulation kernel to notify the environment about events. */
155
    //@{
156
157
    /**
158
     * Notifies the environment that the object no longer exists. The
159
     * user interface should close all inspector windows for the object
160
     * and remove it from object lists currently displayed. cObject's
161
     * destructor automatically calls this function.
162
     */
163
    // note: this cannot be pure virtual, because it has to work even after ev was disposed of
164
    virtual void objectDeleted(cObject *object) {}
165
166
    /**
167
     * Notifies the environment that a component's initialize method is about to be called.
168
     */
169
    virtual void componentInitBegin(cComponent *component, int stage) {}
170
171
    /**
172
     * Notifies the environment that a message was delivered to its destination
173
     * module, that is, a message arrival event occurred. Details can be
174
     * extracted from the message object itself. The user interface
175
     * implementation may use the notification to animate the message on a
176
     * network diagram, to write a log entry, etc.
177
     */
178
    virtual void simulationEvent(cMessage *msg) = 0;
179
180 2f5cc443 Simon Tenbusch
    virtual void simulationEventEnd(double complexity) = 0;
181
182 01873262 Georg Kunz
    /**
183
     * Notifies the environment that a message was sent. Details can be
184
     * extracted from the message object itself. The user interface
185
     * implementation may use the notification to animate the message on a
186
     * network diagram, to write a log entry, etc.
187
     *
188
     * The second argument is non-NULL only when sendDirect() was used, and
189
     * identifies the target gate that was passed to the sendDirect() call.
190
     * (This information is necessary for proper animation: the target gate
191
     * might belong to a compound module and be further connected, and then
192
     * the message will additionally travel through a series of connections
193
     * before it arrives in a simple module.)
194
     */
195
    virtual void messageSent_OBSOLETE(cMessage *msg, cGate *directToGate=NULL) = 0;
196
197
    /**
198
     * Notifies the environment that a message was scheduled.
199
     * @see cSimpleModule::scheduleAt()
200
     */
201
    virtual void messageScheduled(cMessage *msg) = 0;
202
203
    /**
204
     * Notifies the environment that a scheduled message was cancelled.
205
     * @see cSimpleModule::cancelEvent()
206
     */
207
    virtual void messageCancelled(cMessage *msg) = 0;
208
209
    /**
210
     * Notifies the environment that a message is being sent from a
211
     * simple module. beginSend() will be followed by a messageSendDirect()
212
     * (optional, only present when cSimpleModule::sendDirect() was called),
213
     * several messageSendHop() calls (one for each connection in the path),
214
     * and finally an endSend().
215
     */
216
    virtual void beginSend(cMessage *msg) = 0;
217
218
    /** Part of the beginSend() sequence. @see beginSend() */
219
    virtual void messageSendDirect(cMessage *msg, cGate *toGate, simtime_t propagationDelay, simtime_t transmissionDelay) = 0;
220
221
    /** Part of the beginSend() sequence. @see beginSend() */
222
    virtual void messageSendHop(cMessage *msg, cGate *srcGate) = 0;
223
224
    /** Part of the beginSend() sequence. @see beginSend() */
225
    virtual void messageSendHop(cMessage *msg, cGate *srcGate, simtime_t propagationDelay, simtime_t transmissionDelay) = 0;
226
227
    /** Closes a beginSend() sequence. @see beginSend() */
228
    virtual void endSend(cMessage *msg) = 0;
229
230
    /**
231
     * Notifies the environment that a message object is being deleted.
232
     * This is called from the cMessage destructor, so any information added
233
     * to cMessage via subclassing is already lost at the time of the call.
234
     */
235
    virtual void messageDeleted(cMessage *msg) = 0;
236
237
    /**
238
     * Notifies the environment that a module changed parent.
239
     */
240
    virtual void moduleReparented(cModule *module, cModule *oldparent) = 0;
241
242
    /**
243
     * Notifies the environment that one component (module) called a member
244
     * function of another component. This hook enables a graphical user
245
     * interface to animate the method call in the network diagram.
246
     * Pass methodFmt==NULL for Enter_Method_Silent.
247
     */
248
    virtual void componentMethodBegin(cComponent *from, cComponent *to, const char *methodFmt, va_list va, bool silent) = 0;
249
250
    /**
251
     * Notifies the environment that the method entered in the last
252
     * componentMethodBegin() call has exited.
253
     */
254
    virtual void componentMethodEnd() = 0;
255
256
    /**
257
     * Notifies the environment that a module was created. This method is called
258
     * from cModuleType::create(), when the module has already been created
259
     * but buildInside() has not been invoked yet.
260
     */
261
    virtual void moduleCreated(cModule *newmodule) = 0;
262
263
    /**
264
     * Notifies the environment that a module was (more precisely: is being)
265
     * deleted. This method is called from cModule destructor, so the
266
     * "real" type (getClassName() and everything from the actual subclass)
267
     * is already lost at this point, however getName(), getFullName(), getFullPath(),
268
     * gates, parameters (everything that comes from cModule) are still valid.
269
     *
270
     * If a compound module (or a module with dynamically created submodules)
271
     * is deleted, one should not assume anything about the relative order
272
     * moduleDeleted() is called for the module and its submodules.
273
     */
274
    virtual void moduleDeleted(cModule *module) = 0;
275
276
    /**
277
     * Notifies the environment that a gates was created.
278
     */
279
    virtual void gateCreated(cGate *newgate) = 0;
280
281
    /**
282
     * Notifies the environment that a gates was (more precisely: is being)
283
     * deleted.
284
     */
285
    virtual void gateDeleted(cGate *gate) = 0;
286
287
    /**
288
     * Notifies the environment that a connection has been created using
289
     * srcgate->connectTo().
290
     */
291
    virtual void connectionCreated(cGate *srcgate) = 0;
292
293
    /**
294
     * Notifies the environment that a connection has been deleted using
295
     * srcgate->disconnect().
296
     */
297
    virtual void connectionDeleted(cGate *srcgate) = 0;
298
299
    /**
300
     * Notifies the environment that a module or channel display string has
301
     * changed.
302
     */
303
    virtual void displayStringChanged(cComponent *component) = 0;
304
305
    /**
306
     * Called from module destructors, to notify the environment about objects
307
     * that the user did not delete in the module destructor.
308
     */
309
    // Note: this may not be pure virtual, as it may get called even after main()
310
    // exited and StaticEnv was destructed, and we do not want to get a "pure virtual
311
    // method called" error
312
    virtual void undisposedObject(cObject *obj) {}
313
    //@}
314
315
    /** @name Methods called by the simulation kernel to access configuration settings. */
316
    //@{
317
318
    /**
319
     * Called when a module or channel has been created and installed in the model,
320
     * and lets the environment perform extra setup. One use is to add signal
321
     * listeners for result recording.
322
     */
323
    virtual void configure(cComponent *component) = 0;
324
325
    /**
326
     * Assigns the module or channel parameter from the configuration, or
327
     * by asking the user.
328
     */
329
    virtual void readParameter(cPar *parameter) = 0;
330
331
    /**
332
     * Used for parallel distributed simulation. Returns true if the
333
     * named future submodule of parentmod is (or will have any submodule)
334
     * in the local partition, and false otherwise.
335
     *
336
     * Note that for compound modules that contain simple modules in
337
     * several partitions, this function will return true on all those
338
     * partitions.
339
     */
340
    virtual bool isModuleLocal(cModule *parentmod, const char *modname, int index) = 0;
341
342
    /**
343
     * Resolves reference to an XML model configuration file. First argument
344
     * is the file name of the XML document. The optional second argument
345
     * may contain an XPath-like expression to denote an element within
346
     * the XML document. If path is not present, the root element is returned.
347
     *
348
     * See documentation of cXMLElement::getElementByPath() for path syntax.
349
     * There is a difference however: paths starting with "." are not
350
     * accepted, and the first path component must name the root element
351
     * of the document (with getElementByPath() it would match a child element
352
     * of the current element). That is, a leading "/" is always assumed
353
     * at the beginning of the path expression, even if it is not explicitly
354
     * there.
355
     *
356
     * The method throws an exception if the document cannot be found or the
357
     * given path expression is invalid. Returns NULL if the element denoted
358
     * by the path expression does not exist in the document.
359
     *
360
     * The returned object tree should not be modified because cEnvir may
361
     * cache the file and return the same pointer to several callers.
362
     */
363
    virtual cXMLElement *getXMLDocument(const char *filename, const char *path=NULL) = 0;
364
365
    /**
366
     * Removes the given document from the XML document cache (if cached), and
367
     * deletes the object tree from memory. Further getXMLDocument() calls will
368
     * reload the file from the disk. After forgetXMLDocument(), cXMLElement
369
     * objects returned for the same document by getXMLDocument() should
370
     * no longer be referenced. The call has no effect if the given file
371
     * does not exist or has not yet been loaded.
372
     *
373
     * CAUTION: As of version 4.1, this is not a safe operation, as module
374
     * parameters (cPar) of type "xml" hold pointers to the element trees
375
     * returned by getXMLDocument().
376
     */
377
    virtual void forgetXMLDocument(const char *filename) = 0;
378
379
    /**
380
     * Clears the XML document cache, and deletes the cached cXMLElement trees.
381
     *
382
     * CAUTION: As of version 4.1, this is not a safe operation, as module
383
     * parameters (cPar) of type "xml" hold pointers to the element trees
384
     * returned by getXMLDocument(), and this method makes those pointers
385
     * invalid.
386
     */
387
    virtual void flushXMLDocumentCache() = 0;
388
389
    /**
390
     * Called from cSimpleModule, it returns how much extra stack space
391
     * the user interface recommends for activity() simple modules.
392
     */
393
    virtual unsigned getExtraStackForEnvir() const = 0;
394
395
    /**
396
     * Access to the configuration (by default, omnetpp.ini).
397
     * This method is provided here for the benefit of schedulers, parallel
398
     * simulation algorithms and other simulation kernel extensions.
399
     * Models (simple modules) should NOT directly access the configuration --
400
     * they should rely on module parameters to get input.
401
     */
402
    virtual cConfiguration *getConfig() = 0;
403
404
    /**
405
     * Returns the configuration as used by the Envir library. It will throw
406
     * an error if the configuration object does not subclass from cConfigurationEx.
407
     * This method should not be used from the simulation kernel or model code.
408
     */
409
    virtual cConfigurationEx *getConfigEx();
410
    //@}
411
412
    /** @name Input/output methods called from simple modules or the simulation kernel. */
413
    //@{
414
    /**
415
     * Tells if the current environment is graphical or not. (For Tkenv it returns true,
416
     * and with Cmdenv it returns false.) Simple modules can examine this flag
417
     * to decide whether or not they need to bother updating display strings.
418
     */
419
    virtual bool isGUI() const = 0;
420
421
    /**
422
     * Returns true if the simulation is running in an Express or Express-like mode
423
     * where output from <tt>ev&lt;&lt;</tt> and <tt>ev.printf()</tt> statement is
424
     * not printed or logged anywhere but discarded. Model code may make <tt>ev&lt;&lt;</tt>
425
     * statements conditional on this flag to save CPU cycles. For example:
426
     * <pre>
427
     *     if (!ev.isDisabled())  ev << "Packet " << msg->getName() << " received";
428
     * </pre>
429
     *
430
     * which can be abbreviated with the <tt>EV</tt> macro:
431
     *
432
     * <pre>
433
     *     EV << "Packet " << msg->getName() << " received";
434
     * </pre>
435
     */
436
    bool isDisabled() const {return disable_tracing && !record_eventlog;}
437
438
    /**
439
     * Overloaded << operator to make cEnvir behave like an ostream.
440
     * @see getOStream()
441
     */
442
    // implementation note: needed because otherwise the templated version
443
    // would cause ambiguity errors in some cases
444
    cEnvir& operator<<(const std::string& t) {out << t; return *this;}
445
446
    /**
447
     * Overloaded << operator to make cEnvir behave like an ostream.
448
     *
449
     * This method can be used by modules and channels to display debugging output.
450
     * It is up to the user interface implementation to display the text in
451
     * the way it wants. The text is usually associated with the module or channel
452
     * in context (see cSimulation::getContext()), and may get displayed in the
453
     * module's debug window, or enabled/disabled per module.
454
     *
455
     * @see getOStream()
456
     */
457
    template<typename T> cEnvir& operator<<(const T& t) {out << t; return *this;}
458
459
    /**
460
     * Overloaded << operator to handle stream manipulators such as <tt>endl</tt>.
461
     */
462
    cEnvir& operator<<(std::ostream& (t)(std::ostream&)) {out << t; return *this;}
463
464
    /**
465
     * Returns the std::ostream instance where '<<' operators delegate.
466
     * Writes will be eventually delegated to cEnvir::sputn(), after buffering.
467
     */
468
    std::ostream& getOStream() {return out;}
469
470
    /**
471
     * In graphical user interfaces (Tkenv), it pops up a "bubble" over the
472
     * module icon.
473
     */
474
    virtual void bubble(cComponent *component, const char *text) = 0;
475
476
    /**
477
     * Displays the given text in a dialog box. This function should not be
478
     * used by simple modules. Delegates to putsmsg().
479
     */
480
    virtual void printfmsg(const char *fmt,...);
481
482
    /**
483
     * This method can be used by modules and channels to display debugging output.
484
     * It is up to the user interface implementation to display the text in
485
     * the way it wants. The text is usually associated with the module or channel
486
     * in context (see cSimulation::getContext()), and may get displayed in the
487
     * module's debug window, or enabled/disabled per module.
488
     *
489
     * The function's arguments are identical to the standard \<stdio.h\> printf().
490
     * It is recommended to use C++-style I/O (operator<<) instead of this function.
491
     */
492
    // note: non-virtual, delegates to sputn()
493
    virtual int printf(const char *fmt,...);
494
495
    /**
496
     * Flushes the output buffer of ev.printf() and ev<< operations.
497
     * Only some user interfaces need it: it can be useful with Cmdenv which
498
     * writes to the standard output, but no need for it with Tkenv which
499
     * displays all output immediately anyway.
500
     */
501
    virtual cEnvir& flush() = 0;
502
503
    /**
504
     * Interactively prompts the user to enter a string.
505
     */
506
    virtual std::string gets(const char *prompt, const char *defaultreply=NULL) = 0;
507
508
    /**
509
     * Asks the user a yes/no question. The question text is expected
510
     * in printf() format (format string + arguments). The return value
511
     * is true for "yes", and false for "no".
512
     */
513
    // note: non-virtual, delegates to askyesno()
514
    virtual bool askYesNo(const char *fmt,...);
515
    //@}
516
517
    /** @name Access to RNGs. */
518
    //@{
519
520
    /**
521
     * Returns the number of RNGs available for the simulation
522
     * ("num-rngs=" omnetpp.ini setting).
523
     */
524
    virtual int getNumRNGs() const = 0;
525
526
    /**
527
     * Returns pointer to "physical" RNG k (0 <= k < getNumRNGs()).
528
     */
529
    virtual cRNG *getRNG(int k) = 0;
530
531
        /**
532
     * Sets up RNG mapping (which maps module-local RNG numbers to "physical"
533
     * RNGs) for the given module or channel, by calling its setRNGMap() function.
534
     */
535
    virtual void getRNGMappingFor(cComponent *component) = 0;
536
    //@}
537
538
    /** @name Methods for recording data from output vectors.
539
     *
540
     * These are functions cOutVector internally relies on.
541
     *
542
     * The behavior of these functions can be changed by plugging in a different
543
     * cOutputVectorManager object into the user interface library. (Or alternatively,
544
     * by reimplementing the whole cEnvir of course).
545
     */
546
    //@{
547
548
    /**
549
     * This method is intended to be called by cOutVector objects to register
550
     * themselves. The returned value is a handle that identifies the vector
551
     * in subsequent recordInOutputVector() and deregisterOutputVector()
552
     * calls. The handle may have any value (it does not have to be a valid
553
     * pointer), but it should NOT be NULL.
554
     */
555
    virtual void *registerOutputVector(const char *modulename, const char *vectorname) = 0;
556
557
    /**
558
     * cOutVector objects must deregister themselves when they are no longer needed.
559
     */
560
    virtual void deregisterOutputVector(void *vechandle) = 0;
561
562
    /**
563
     * This method is called when an attribute of the output vector is set.
564
     */
565
    virtual void setVectorAttribute(void *vechandle, const char *name, const char *value) = 0;
566
567
    /**
568
     * This method is intended to be called by cOutVector objects to write
569
     * a value into the output vector. The return value is true if the data was
570
     * actually recorded, and false if it was not recorded (because of filtering, etc.)
571
     */
572
    virtual bool recordInOutputVector(void *vechandle, simtime_t t, double value) = 0;
573
    //@}
574
575
    /** @name Scalar statistics.
576
     *
577
     * The method cComponent::recordScalar() function internally relies on.
578
     *
579
     * The behavior of this function can be changed by plugging in a different
580
     * cOutputScalarManager object into the user interface library. (Or alternatively,
581
     * by reimplementing the whole cEnvir of course).
582
     */
583
    //@{
584
585
    /**
586
     * Records a double scalar result, in a default configuration into the scalar result file.
587
     */
588
    virtual void recordScalar(cComponent *component, const char *name, double value, opp_string_map *attributes=NULL) = 0;
589
590
    /**
591
     * Records a statistic object (histogram, etc) into the scalar result file.
592
     * This operation may invoke the transform() method on the histogram object.
593
     */
594
    virtual void recordStatistic(cComponent *component, const char *name, cStatistic *statistic, opp_string_map *attributes=NULL) = 0;
595
    //@}
596
597
    /** @name Management of streams where snapshots can be written.
598
     *
599
     * The behavior of these functions can be changed by plugging in a different
600
     * cSnapshotManager object into the user interface library. (Or alternatively,
601
     * by reimplementing the whole cEnvir of course).
602
     */
603
    //@{
604
605
    /**
606
     * Returns a stream where a snapshot can be written. Called from cSimulation::snapshot().
607
     */
608
    virtual std::ostream *getStreamForSnapshot() = 0;
609
610
    /**
611
     * Releases a stream after a snapshot was written.
612
     */
613
    virtual void releaseStreamForSnapshot(std::ostream *os) = 0;
614
    //@}
615
616
    /** @name Miscellaneous functions. */
617
    //@{
618
    /**
619
     * Access to original command-line arguments.
620
     */
621
    virtual int getArgCount() const = 0;
622
623
    /**
624
     * Access to original command-line arguments.
625
     */
626
    virtual char **getArgVector() const = 0;
627
628
    /**
629
     * Returns the partitionID when parallel simulation is active.
630
     */
631
    virtual int getParsimProcId() const = 0;
632
633
    /**
634
     * Returns the number of partitions when parallel simulation is active;
635
     * otherwise it returns 0.
636
     */
637
    virtual int getParsimNumPartitions() const = 0;
638
639
    /**
640
     * The function underlying cSimulation::getUniqueNumber().
641
     */
642
    virtual unsigned long getUniqueNumber() = 0;
643
644
    /**
645
     * May be called from the simulation while actively waiting
646
     * for some external condition to occur -- for example from
647
     * blocking receive in parallel simulation, or during wait
648
     * in real-time simulation.
649
     *
650
     * In a graphical user interface, this method may take care
651
     * of display redraw and handling user interaction (including
652
     * handling of the Stop button).
653
     *
654
     * Normally returns false. A true value means the user wants to
655
     * abort waiting (e.g. pushed the Stop button).
656
     */
657
    virtual bool idle() = 0;
658
    //@}
659
};
660
661
662
/**
663
 * The interface for cEnvir objects that can be instantiated as a user interface
664
 * like Cmdenv and Tkenv.
665
 *
666
 * @ingroup Envir
667
 * @ingroup EnvirExtensions
668
 */
669
class SIM_API cRunnableEnvir : public cEnvir
670
{
671
  public:
672
    /**
673
     * Runs the user interface. The return value will become the exit code
674
     * of the simulation program.
675
     */
676
    virtual int run(int argc, char *argv[], cConfiguration *cfg) = 0;
677
};
678
679
NAMESPACE_END
680
681
#endif
682