Statistics
| Branch: | Revision:

root / include / csimplemodule.h @ ffa9279f

History | View | Annotate | Download (18.1 KB)

1
//==========================================================================
2
//   CSIMPLEMODULE.H  -  header for
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//
7
//  Declaration of the following classes:
8
//    cSimpleModule  : base for simple module objects
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 __CSIMPLEMODULE_H
21
#define __CSIMPLEMODULE_H
22

    
23
#include "cmodule.h"
24
#include "cnumgen.h"
25

    
26
NAMESPACE_BEGIN
27

    
28
class cQueue;
29
class cCoroutine;
30

    
31
/**
32
 * Base class for all simple module classes. cSimpleModule, although packed
33
 * with simulation-related functionality, does not do anything useful by itself:
34
 * one has to subclass from it and redefine one or more virtual member
35
 * functions to make it do useful work. These functions are:
36
 *
37
 *    - void initialize()
38
 *    - void handleMessage(cMessage *msg)
39
 *    - void activity()
40
 *    - void finish()
41
 *
42
 * initialize() is called after \opp created the module. Multi-stage
43
 * initialization can be achieved by redefining the initialize(int stage)
44
 * method instead, and also redefining the numInitStages() const method to
45
 * return the required number of stages.
46
 *
47
 * One has to redefine handleMessage() to contain the internal logic of
48
 * the module. handleMessage() is called by the simulation kernel when the
49
 * module receives a message. (An alternative to handleMessage() is
50
 * activity(), but activity() is not recommended for serious model development
51
 * because of scalability and debugging issues. activity() also tends to lead
52
 * to messy module implementations.)
53
 *
54
 * You can send() messages to other modules, or use scheduleAt()+cancelEvent()
55
 * to implement delays, timers or timeouts. Messages sent or scheduled (but
56
 * not cancelled) are delivered to modules via handleMessage(), or, when using
57
 * activity(), via receive().
58
 *
59
 * The finish() functions are called when the simulation terminates
60
 * successfully. Typical use of finish() is recording statistics collected
61
 * during simulation.
62
 *
63
 * @ingroup SimCore
64
 */
65
class SIM_API cSimpleModule : public cModule, public cNumberGenerator //implies noncopyable
66
{
67
    friend class cModule;
68
    friend class cSimulation;
69

    
70
  private:
71
    enum {
72
        FL_USESACTIVITY = 512,   // uses activity() or handleMessage()
73
        FL_ISTERMINATED = 1024,  // for both activity and handleMessage modules
74
        FL_STACKALREADYUNWOUND = 2048, // only for activity modules
75
    };
76
    cMessage *timeoutmsg;   // msg used in wait() and receive() with timeout
77
    cCoroutine *coroutine;
78

    
79
    static bool stack_cleanup_requested; // 'true' value asks activity() to throw a cStackCleanupException
80
    static cSimpleModule *after_cleanup_transfer_to; // transfer back to this module (or to main)
81

    
82
  private:
83
    // internal use
84
    static void activate(void *p);
85

    
86
  protected:
87
    // internal use
88
    virtual void arrived(cMessage *msg, cGate *ongate, simtime_t t);
89

    
90
    // internal: sets the module id.
91
    virtual void setId(int n);
92

    
93
  protected:
94
    /** @name Hooks for defining module behavior.
95
     *
96
     * Exactly one of activity() and handleMessage() must be redefined
97
     * by the user to add functionality to the simple module. See the
98
     * manual for detailed guidance on how use to these two methods.
99
     *
100
     * These methods are made protected because they shouldn't be called
101
     * directly from outside.
102
     */
103
    //@{
104

    
105
    /**
106
     * Should be redefined to contain the module activity function.
107
     * For several good reasons, you should prefer handleMessage() to activity().
108
     * This default implementation issues an error message (throws cRuntimeError).
109
     */
110
    virtual void activity();
111

    
112
    /**
113
     * Should be redefined to contain the module's message handling function.
114
     * This default implementation issues an error message (throws cRuntimeError).
115
     */
116
    virtual void handleMessage(cMessage *msg);
117
    //@}
118

    
119
  public:
120
    /** @name Constructors, destructor, assignment. */
121
    //@{
122
    /**
123
     * Constructor. Note that module objects should not be created directly,
124
     * only via their cModuleType objects. See cModule constructor for more info.
125
     * The stacksize parameter should only be used with simple modules using
126
     * activity().
127
     */
128
    cSimpleModule(unsigned stacksize = 0);
129

    
130
    /**
131
     * COMPATIBILITY. This constructor is only provided to make it possible
132
     * to write simple modules that do not use the Module_Class_Members
133
     * macro and can also be compiled with OMNeT++ versions earlier than
134
     * 3.2. The first two args are unused in this and later versions.
135
     */
136
    cSimpleModule(const char *dummy1, cModule *dummy2, unsigned stacksize);
137

    
138
    /**
139
     * Destructor.
140
     */
141
    virtual ~cSimpleModule();
142
    //@}
143

    
144
    /*
145
     * Returns true if Module is capable of Horizon specific parallel execution
146
     * Called in doOneEvent
147
     * Overridden in cAsyncmodule
148
     */
149
    virtual bool isAsyncModule() const {
150
            return false;
151
    }
152

    
153
    /** @name Redefined cObject member functions. */
154
    //@{
155
    /**
156
     * Produces a one-line description of the object's contents.
157
     * See cObject for more details.
158
     */
159
    virtual std::string info() const;
160

    
161
    /**
162
     * Calls v->visit(this) for each contained object.
163
     * See cObject for more details.
164
     */
165
    virtual void forEachChild(cVisitor *v);
166
    //@}
167

    
168
    /** @name Redefined cModule functions. */
169
    //@{
170

    
171
    /**
172
     * Creates a starting message for the module.
173
     */
174
    virtual void scheduleStart(simtime_t t);
175

    
176
    /**
177
     * Deletes the module and all its (dynamically created) submodules.
178
     *
179
     * A running module can also delete itself. When an activity()-based
180
     * simple module deletes itself from within its activity(), the
181
     * deleteModule() call will not return (it throws an exception which
182
     * gets caught by the simulation kernel, and the simulation kernel
183
     * will delete the module).
184
     *
185
     * When a handleMessage()-based module deletes itself, the deleteModule()
186
     * returns normally -- then, of course, the code should not try to
187
     * access data members or functions of the deleted module, an should
188
     * return as soon as possible.
189
     */
190
    virtual void deleteModule();
191
    //@}
192

    
193
    /** @name Information about the module. */
194
    //@{
195

    
196
    /**
197
     * Returns the event handling scheme: activity() or handleMessage().
198
     */
199
    bool usesActivity() const  {return flags&FL_USESACTIVITY;}
200

    
201
    /**
202
     * Returns true if the module has already terminated, by having called end()
203
     * or returning from the activity() method.
204
     */
205
    bool isTerminated() const {return flags&FL_ISTERMINATED;}
206
    //@}
207

    
208
    /** @name Debugging aids. */
209
    //@{
210
    /**
211
     * To be called from module functions. Outputs textual information
212
     * about all objects of the simulation (including the objects created
213
     * in module functions by the user!) into the snapshot file. The
214
     * output is detailed enough to be used for debugging the simulation:
215
     * by regularly calling snapshot(), one can trace how the
216
     * values of variables, objects changed over the simulation. The
217
     * arguments: label is a string that will appear in the
218
     * output file; obj is the object whose inside is of interest.
219
     * By default, the whole simulation (all modules etc) will be written
220
     * out.
221
     *
222
     * Tkenv also supports making snapshots manually, from menu.
223
     *
224
     * See also class cWatch and the WATCH() macro.
225
     */
226
    bool snapshot(cObject *obj=NULL, const char *label=NULL);
227
    //@}
228

    
229
    /** @name Message sending. */
230
    //@{
231

    
232
    /**
233
     * Sends a message through the gate given with its ID.
234
     */
235
    int send(cMessage *msg, int gateid)  {return sendDelayed(msg, SIMTIME_ZERO, gateid);}
236

    
237
    /**
238
     * Sends a message through the gate given with its name and index
239
     * (if multiple gate).
240
     */
241
    int send(cMessage *msg, const char *gatename, int gateindex=-1)  {return sendDelayed(msg, SIMTIME_ZERO, gatename, gateindex);}
242

    
243
    /**
244
     * Sends a message through the gate given with its pointer.
245
     */
246
    int send(cMessage *msg, cGate *outputgate)  {return sendDelayed(msg, SIMTIME_ZERO, outputgate);}
247

    
248
    /**
249
     * Delayed sending. Sends a message through the gate given with
250
     * its index as if it was sent delay seconds later.
251
     */
252
    int sendDelayed(cMessage *msg, simtime_t delay, int gateid);
253

    
254
    /**
255
     * Delayed sending. Sends a message through the gate given with
256
     * its name and index (if multiple gate) as if it was sent delay
257
     * seconds later.
258
     */
259
    int sendDelayed(cMessage *msg, simtime_t delay, const char *gatename, int gateindex=-1);
260

    
261
    /**
262
     * Sends a message through the gate given with its pointer as if
263
     * it was sent delay seconds later.
264
     */
265
    int sendDelayed(cMessage *msg, simtime_t delay, cGate *outputgate);
266

    
267
    /**
268
     * Sends a message directly to another module, with zero propagation delay
269
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
270
     * for a more detailed description.
271
     */
272
    int sendDirect(cMessage *msg, cModule *mod, const char *inputGateName, int gateIndex=-1);
273

    
274
    /**
275
     * Sends a message directly to another module, with zero propagation delay
276
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
277
     * for a more detailed description.
278
     */
279
    int sendDirect(cMessage *msg, cModule *mod, int inputGateId);
280

    
281
    /**
282
     * Sends a message directly to another module, with zero propagation delay
283
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
284
     * for a more detailed description.
285
     */
286
    int sendDirect(cMessage *msg, cGate *inputGate);
287

    
288
    /**
289
     * Sends a message directly to another module.
290
     * See sendDirect(cMessage *, simtime_t, simtime_t, cGate *) for a more
291
     * detailed description.
292
     */
293
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cModule *mod, const char *inputGateName, int gateIndex=-1);
294

    
295
    /**
296
     * See sendDirect(cMessage *, simtime_t, simtime_t, cGate *) for a more
297
     * detailed description.
298
     */
299
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cModule *mod, int inputGateId);
300

    
301
    /**
302
     * Send a message directly to another module.
303
     *
304
     * If the gate is further connected (i.e. getNextGate()!=NULL), the
305
     * message will follow the connections that start at that gate.
306
     * For example, when sending to an input gate of a compound module,
307
     * the message will follow the connections to the inside of the compound module.
308
     *
309
     * It is permitted to send to an output gate, which will also cause the
310
     * message to follow the connections starting at that gate.
311
     * This can be useful, for example, when several submodules are sending
312
     * to a single output gate of their parent module.
313
     *
314
     * It is not permitted to send to a gate of a compound module which is not
315
     * further connected (i.e. getNextGate()==NULL), as this would cause the message
316
     * to arrive at a compound module.
317
     *
318
     * Also, it is not permitted to send to a gate which is otherwise connected
319
     * i.e. where getPreviousGate()!=NULL. This means that modules MUST have
320
     * dedicated gates for receiving via sendDirect(). You cannot have a gate
321
     * which receives messages via both connections and sendDirect().
322
     *
323
     * When a nonzero duration is given, that signifies the duration of the packet
324
     * transmission, that is, the time difference between the transmission (or
325
     * reception) of the start of the packet and that of the end of the packet.
326
     * The destination module can choose whether it wants the simulation kernel
327
     * to deliver the packet object to it at the start or at the end of the
328
     * reception. The default is the latter; the module can change it by calling
329
     * setDeliverOnReceptionStart() on the final input gate (that is, on
330
     * inputGate->getPathEndGate()). setDeliverOnReceptionStart() needs to be
331
     * called in advance, for example in the initialize() method of the module.
332
     * When a module receives a packet, it can call the isReceptionStart() and
333
     * getDuration() methods on the packet to find out whether it represents
334
     * the start or the end of the reception, and the duration of the
335
     * transmission.
336
     *
337
     * For messages that are not packets (i.e. not subclassed from cPacket),
338
     * the duration parameter is ignored, that is, it will be taken as zero.
339
     */
340
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cGate *inputGate);
341
    //@}
342

    
343
    /** @name Self-messages. */
344
    //@{
345

    
346
    /**
347
     * Schedules a self-message. It will be delivered back to the module
348
     * via receive() or handleMessage() at simulation time t. This method
349
     * is the way you can implement timers or timeouts. Timers can also
350
     * be cancelled via cancelEvent() (See below.)
351
     *
352
     * When the message is delivered at the module, you can call
353
     * <tt>msg->isSelfMessage()</tt> to tell it apart from messages arriving
354
     * from other modules. <tt>msg->getKind()</tt> can be used to further
355
     * classify it, or of you need to manage an unbounded number of timers,
356
     * you can set <tt>msg->getContextPointer()</tt> before scheduling to
357
     * point to the data structure the message belongs to -- this way
358
     * you can avoid having to search through lists or other data structures
359
     * to find out where a just-arrived self-message belongs.
360
     *
361
     * cancelEvent() can be used to cancel the self-message before it arrives.
362
     * This is useful for implementing timeouts: if the event occurs "in time"
363
     * (before timeout), the scheduled self-message can be cancelled.
364
     *
365
     * Given a cMessage pointer, you can check whether it is currently
366
     * scheduled by calling <tt>msg->isScheduled()</tt>. If it is scheduled,
367
     * you cannot schedule it again without calling cancelEvent() first.
368
     * However, after the message was delivered to the module or cancelled,
369
     * you can schedule it again -- so you can reuse the same message
370
     * object for timeouts over and over during the whole simulation.
371
     */
372
    int scheduleAt(simtime_t t, cMessage *msg);
373

    
374
    /**
375
     * Removes the given message from the future events. The message
376
     * needs to have been sent using the scheduleAt() function.
377
     * This function can be used to cancel a timer implemented with scheduleAt().
378
     * If the message is not currently scheduled, nothing happens.
379
     */
380
    cMessage *cancelEvent(cMessage *msg);
381

    
382
    /**
383
     * Invokes cancelEvent() on the message (in case it is scheduled), then
384
     * deletes it. A NULL pointer is also accepted, then the method does nothing.
385
     * This method is especially useful in simple module destructors, to dispose
386
     * of self-messages that the module has allocated.
387
     */
388
    void cancelAndDelete(cMessage *msg);
389
    //@}
390

    
391
    /** @name Receiving messages.
392
     *
393
     * These methods may only be invoked from activity()-based simple modules.
394
     */
395
    //@{
396

    
397
    /**
398
     * Remove the next message from the event queue and return a pointer
399
     * to it.
400
     */
401
    cMessage *receive();
402

    
403
    /**
404
     * Removes the next message from the event queue and returns a pointer
405
     * to it. If there is no message in the event
406
     * queue, the function waits with t timeout until a message will be
407
     * available. If the timeout expires and there is still no message
408
     * in the queue, the function returns NULL.
409
     */
410
    cMessage *receive(simtime_t timeout);
411
    //@}
412

    
413
    /** @name Waiting. */
414
    //@{
415

    
416
    /**
417
     * Waits for the given interval. (Some other simulators call this
418
     * functionality hold()).
419
     * It is intended for use only if you do not expect other messages
420
     * to arrive at the module during the wait period. To assert this,
421
     * it throws an exception if a message arrives during the wait.
422
     *
423
     * If you expect to receive messages during the call, you should use
424
     * waitAndEnqueue() instead.
425
     *
426
     * This function can only be used with activity(), but not with
427
     * handleMessage().
428
     */
429
    void wait(simtime_t time);
430

    
431
    /**
432
     * Waits for the given interval. The messages received during the wait
433
     * period are inserted into the queue passed as argument.
434
     *
435
     * This function can only be used with activity(), but not with
436
     * handleMessage().
437
     */
438
    void waitAndEnqueue(simtime_t time, cQueue *queue);
439
    //@}
440

    
441
    /** @name Stopping the module or the simulation. */
442
    //@{
443
    /**
444
     * Causes the whole simulation to stop. The implementation simply
445
     * throws a cTerminationException.
446
     */
447
    void endSimulation();
448

    
449
    /**
450
     * May only be invoked from activity()-based simple modules.
451
     * Execution of the simple module stops in this call, and any further
452
     * messages sent to module will cause a runtime error.
453
     */
454
    void halt();
455

    
456
    /**
457
     * Equivalent to <tt>throw cRuntimeError(<i>same argument list</i>)</tt>.
458
     */
459
    void error(const char *format,...) const;
460
    //@}
461

    
462
    /** @name Coroutine stack info. Useful only if module uses activity(). */
463
    //@{
464

    
465
    /**
466
     * Returns true if there was a stack overflow during execution of the
467
     * coroutine. (Not implemented for every coroutine package - see cCoroutine
468
     * documentation for more info.) If the module uses handleMessage(),
469
     * this method always returns false.
470
     *
471
     * @see cCoroutine
472
     */
473
    virtual bool hasStackOverflow() const;
474

    
475
    /**
476
     * Returns the stack size of the coroutine. If the module uses handleMessage(),
477
     * this method always returns 0.
478
     */
479
    virtual unsigned getStackSize() const;
480

    
481
    /**
482
     * Returns the amount of stack actually used by the coroutine.
483
     * (Not implemented for every coroutine package - see cCoroutine
484
     * documentation for more info.) If the module uses handleMessage(),
485
     * this method always returns 0.
486
     *
487
     * @see cCoroutine
488
     */
489
    virtual unsigned getStackUsage() const;
490
    //@}
491
};
492

    
493
NAMESPACE_END
494

    
495

    
496
#endif
497