Statistics
| Branch: | Revision:

root / include / csimplemodule.h @ 47c4b975

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

    
25
NAMESPACE_BEGIN
26

    
27
class cQueue;
28
class cCoroutine;
29

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
492
NAMESPACE_END
493

    
494

    
495
#endif
496