Statistics
| Branch: | Revision:

root / include / csimplemodule.h @ master

History | View | Annotate | Download (21.2 KB)

1 01873262 Georg Kunz
//==========================================================================
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 fbe00e73 Mirko Stoffers
  Copyright (C) 2009 Georg Kunz
16 01873262 Georg Kunz

17
  This file is distributed WITHOUT ANY WARRANTY. See the file
18
  `license' for details on this and other legal matters.
19
*--------------------------------------------------------------*/
20
21
#ifndef __CSIMPLEMODULE_H
22
#define __CSIMPLEMODULE_H
23
24 fbe00e73 Mirko Stoffers
#include <pthread.h>
25
#include <semaphore.h>
26
27 01873262 Georg Kunz
#include "cmodule.h"
28
29 fbe00e73 Mirko Stoffers
#ifdef ATOMIC_OPS_DEBUG
30
        #include "catomicopsdebug.h"
31
#else
32
        #include <atomic_ops.h>
33
#endif
34
35 01873262 Georg Kunz
NAMESPACE_BEGIN
36
37
class cQueue;
38
class cCoroutine;
39
40
/**
41
 * Base class for all simple module classes. cSimpleModule, although packed
42
 * with simulation-related functionality, does not do anything useful by itself:
43
 * one has to subclass from it and redefine one or more virtual member
44
 * functions to make it do useful work. These functions are:
45
 *
46
 *    - void initialize()
47
 *    - void handleMessage(cMessage *msg)
48
 *    - void activity()
49
 *    - void finish()
50
 *
51
 * initialize() is called after \opp created the module. Multi-stage
52
 * initialization can be achieved by redefining the initialize(int stage)
53
 * method instead, and also redefining the numInitStages() const method to
54
 * return the required number of stages.
55
 *
56
 * One has to redefine handleMessage() to contain the internal logic of
57
 * the module. handleMessage() is called by the simulation kernel when the
58
 * module receives a message. (An alternative to handleMessage() is
59
 * activity(), but activity() is not recommended for serious model development
60
 * because of scalability and debugging issues. activity() also tends to lead
61
 * to messy module implementations.)
62
 *
63
 * You can send() messages to other modules, or use scheduleAt()+cancelEvent()
64
 * to implement delays, timers or timeouts. Messages sent or scheduled (but
65
 * not cancelled) are delivered to modules via handleMessage(), or, when using
66
 * activity(), via receive().
67
 *
68
 * The finish() functions are called when the simulation terminates
69
 * successfully. Typical use of finish() is recording statistics collected
70
 * during simulation.
71
 *
72
 * @ingroup SimCore
73
 */
74 08285dff Mirko Stoffers
class SIM_API cSimpleModule : public cModule //implies noncopyable
75 01873262 Georg Kunz
{
76
    friend class cModule;
77
    friend class cSimulation;
78
79
  private:
80
    enum {
81
        FL_USESACTIVITY = 512,   // uses activity() or handleMessage()
82
        FL_ISTERMINATED = 1024,  // for both activity and handleMessage modules
83
        FL_STACKALREADYUNWOUND = 2048, // only for activity modules
84
    };
85
    cMessage *timeoutmsg;   // msg used in wait() and receive() with timeout
86
    cCoroutine *coroutine;
87
88
    static bool stack_cleanup_requested; // 'true' value asks activity() to throw a cStackCleanupException
89
    static cSimpleModule *after_cleanup_transfer_to; // transfer back to this module (or to main)
90
91 fbe00e73 Mirko Stoffers
  private: // Horizon
92
    // the two different execution states: either handleMessage is called
93
    // synchronously by the scheduler or asynchronously (to the scheduler)
94
    // by a worker thread
95
    enum ExecutionStates
96
    {
97
        synchronous,
98
        asynchronous
99
    };
100
101
    // current state of execution
102
    ExecutionStates executionState;
103
104
    // new messages may only be scheduled with timestamps >= this value
105
    simtime_t t_end;
106
107
    // priority of the current event
108
    short currentEventPriority;
109
110
    // shall zero duration events be executed in parallel
111
    bool parZeroDur;
112
113
    // no worker is active inside this module
114
    static const AO_t NOT_BUSY = 0;
115
116
    // a worker is active inside this module
117
    static const AO_t BUSY     = 1;
118
119
    // flag indicating that a thread is processing an event within this module
120
    AO_t busy;
121
122
    // how many messages did a given event send?
123
    unsigned int scheduledMessageCount;
124
125
    //
126
    unsigned int executionOrderId;
127
128
    // current simulation time within this module
129
    simtime_t now;
130
131
    /**
132
     * update meta data needed for event execution
133
     */
134
    void prepareHandleMessage(cMessage* msg);
135
136
    /**
137
     * set extended meta data of a message upon sending.
138
     */
139
    void setMessageMetaData(cMessage* msg);
140
141 01873262 Georg Kunz
  private:
142
    // internal use
143
    static void activate(void *p);
144
145
  protected:
146
    // internal use
147
    virtual void arrived(cMessage *msg, cGate *ongate, simtime_t t);
148
149
    // internal: sets the module id.
150
    virtual void setId(int n);
151
152
  protected:
153
    /** @name Hooks for defining module behavior.
154
     *
155
     * Exactly one of activity() and handleMessage() must be redefined
156
     * by the user to add functionality to the simple module. See the
157
     * manual for detailed guidance on how use to these two methods.
158
     *
159
     * These methods are made protected because they shouldn't be called
160
     * directly from outside.
161
     */
162
    //@{
163
164
    /**
165
     * Should be redefined to contain the module activity function.
166
     * For several good reasons, you should prefer handleMessage() to activity().
167
     * This default implementation issues an error message (throws cRuntimeError).
168
     */
169
    virtual void activity();
170
171
    /**
172
     * Should be redefined to contain the module's message handling function.
173
     * This default implementation issues an error message (throws cRuntimeError).
174
     */
175
    virtual void handleMessage(cMessage *msg);
176
    //@}
177
178
  public:
179
    /** @name Constructors, destructor, assignment. */
180
    //@{
181
    /**
182
     * Constructor. Note that module objects should not be created directly,
183
     * only via their cModuleType objects. See cModule constructor for more info.
184
     * The stacksize parameter should only be used with simple modules using
185
     * activity().
186
     */
187
    cSimpleModule(unsigned stacksize = 0);
188
189
    /**
190
     * COMPATIBILITY. This constructor is only provided to make it possible
191
     * to write simple modules that do not use the Module_Class_Members
192
     * macro and can also be compiled with OMNeT++ versions earlier than
193
     * 3.2. The first two args are unused in this and later versions.
194
     */
195
    cSimpleModule(const char *dummy1, cModule *dummy2, unsigned stacksize);
196
197
    /**
198
     * Destructor.
199
     */
200
    virtual ~cSimpleModule();
201
    //@}
202
203
    /** @name Redefined cObject member functions. */
204
    //@{
205
    /**
206
     * Produces a one-line description of the object's contents.
207
     * See cObject for more details.
208
     */
209
    virtual std::string info() const;
210
211
    /**
212
     * Calls v->visit(this) for each contained object.
213
     * See cObject for more details.
214
     */
215
    virtual void forEachChild(cVisitor *v);
216
    //@}
217
218
    /** @name Redefined cModule functions. */
219
    //@{
220
221
    /**
222
     * Creates a starting message for the module.
223
     */
224
    virtual void scheduleStart(simtime_t t);
225
226
    /**
227
     * Deletes the module and all its (dynamically created) submodules.
228
     *
229
     * A running module can also delete itself. When an activity()-based
230
     * simple module deletes itself from within its activity(), the
231
     * deleteModule() call will not return (it throws an exception which
232
     * gets caught by the simulation kernel, and the simulation kernel
233
     * will delete the module).
234
     *
235
     * When a handleMessage()-based module deletes itself, the deleteModule()
236
     * returns normally -- then, of course, the code should not try to
237
     * access data members or functions of the deleted module, an should
238
     * return as soon as possible.
239
     */
240
    virtual void deleteModule();
241
    //@}
242
243
    /** @name Information about the module. */
244
    //@{
245
246
    /**
247
     * Returns the event handling scheme: activity() or handleMessage().
248
     */
249
    bool usesActivity() const  {return flags&FL_USESACTIVITY;}
250
251
    /**
252
     * Returns true if the module has already terminated, by having called end()
253
     * or returning from the activity() method.
254
     */
255
    bool isTerminated() const {return flags&FL_ISTERMINATED;}
256
    //@}
257
258
    /** @name Debugging aids. */
259
    //@{
260
    /**
261
     * To be called from module functions. Outputs textual information
262
     * about all objects of the simulation (including the objects created
263
     * in module functions by the user!) into the snapshot file. The
264
     * output is detailed enough to be used for debugging the simulation:
265
     * by regularly calling snapshot(), one can trace how the
266
     * values of variables, objects changed over the simulation. The
267
     * arguments: label is a string that will appear in the
268
     * output file; obj is the object whose inside is of interest.
269
     * By default, the whole simulation (all modules etc) will be written
270
     * out.
271
     *
272
     * Tkenv also supports making snapshots manually, from menu.
273
     *
274
     * See also class cWatch and the WATCH() macro.
275
     */
276
    bool snapshot(cObject *obj=NULL, const char *label=NULL);
277
    //@}
278
279
    /** @name Message sending. */
280
    //@{
281
282
    /**
283
     * Sends a message through the gate given with its ID.
284
     */
285 fbe00e73 Mirko Stoffers
    int send(cMessage *msg, int gateid);
286 01873262 Georg Kunz
287
    /**
288
     * Sends a message through the gate given with its name and index
289
     * (if multiple gate).
290
     */
291 fbe00e73 Mirko Stoffers
    int send(cMessage *msg, const char *gatename, int gateindex=-1);
292 01873262 Georg Kunz
293
    /**
294
     * Sends a message through the gate given with its pointer.
295
     */
296 fbe00e73 Mirko Stoffers
    int send(cMessage *msg, cGate *outputgate);
297 01873262 Georg Kunz
298
    /**
299
     * Delayed sending. Sends a message through the gate given with
300
     * its index as if it was sent delay seconds later.
301
     */
302
    int sendDelayed(cMessage *msg, simtime_t delay, int gateid);
303
304
    /**
305
     * Delayed sending. Sends a message through the gate given with
306
     * its name and index (if multiple gate) as if it was sent delay
307
     * seconds later.
308
     */
309
    int sendDelayed(cMessage *msg, simtime_t delay, const char *gatename, int gateindex=-1);
310
311
    /**
312
     * Sends a message through the gate given with its pointer as if
313
     * it was sent delay seconds later.
314
     */
315
    int sendDelayed(cMessage *msg, simtime_t delay, cGate *outputgate);
316
317
    /**
318
     * Sends a message directly to another module, with zero propagation delay
319
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
320
     * for a more detailed description.
321
     */
322
    int sendDirect(cMessage *msg, cModule *mod, const char *inputGateName, int gateIndex=-1);
323
324
    /**
325
     * Sends a message directly to another module, with zero propagation delay
326
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
327
     * for a more detailed description.
328
     */
329
    int sendDirect(cMessage *msg, cModule *mod, int inputGateId);
330
331
    /**
332
     * Sends a message directly to another module, with zero propagation delay
333
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
334
     * for a more detailed description.
335
     */
336
    int sendDirect(cMessage *msg, cGate *inputGate);
337
338
    /**
339
     * Sends a message directly to another module.
340
     * See sendDirect(cMessage *, simtime_t, simtime_t, cGate *) for a more
341
     * detailed description.
342
     */
343
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cModule *mod, const char *inputGateName, int gateIndex=-1);
344
345
    /**
346
     * See sendDirect(cMessage *, simtime_t, simtime_t, cGate *) for a more
347
     * detailed description.
348
     */
349
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cModule *mod, int inputGateId);
350
351
    /**
352
     * Send a message directly to another module.
353
     *
354
     * If the gate is further connected (i.e. getNextGate()!=NULL), the
355
     * message will follow the connections that start at that gate.
356
     * For example, when sending to an input gate of a compound module,
357
     * the message will follow the connections to the inside of the compound module.
358
     *
359
     * It is permitted to send to an output gate, which will also cause the
360
     * message to follow the connections starting at that gate.
361
     * This can be useful, for example, when several submodules are sending
362
     * to a single output gate of their parent module.
363
     *
364
     * It is not permitted to send to a gate of a compound module which is not
365
     * further connected (i.e. getNextGate()==NULL), as this would cause the message
366
     * to arrive at a compound module.
367
     *
368
     * Also, it is not permitted to send to a gate which is otherwise connected
369
     * i.e. where getPreviousGate()!=NULL. This means that modules MUST have
370
     * dedicated gates for receiving via sendDirect(). You cannot have a gate
371
     * which receives messages via both connections and sendDirect().
372
     *
373
     * When a nonzero duration is given, that signifies the duration of the packet
374
     * transmission, that is, the time difference between the transmission (or
375
     * reception) of the start of the packet and that of the end of the packet.
376
     * The destination module can choose whether it wants the simulation kernel
377
     * to deliver the packet object to it at the start or at the end of the
378
     * reception. The default is the latter; the module can change it by calling
379
     * setDeliverOnReceptionStart() on the final input gate (that is, on
380
     * inputGate->getPathEndGate()). setDeliverOnReceptionStart() needs to be
381
     * called in advance, for example in the initialize() method of the module.
382
     * When a module receives a packet, it can call the isReceptionStart() and
383
     * getDuration() methods on the packet to find out whether it represents
384
     * the start or the end of the reception, and the duration of the
385
     * transmission.
386
     *
387
     * For messages that are not packets (i.e. not subclassed from cPacket),
388
     * the duration parameter is ignored, that is, it will be taken as zero.
389
     */
390
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cGate *inputGate);
391
    //@}
392
393
    /** @name Self-messages. */
394
    //@{
395
396
    /**
397
     * Schedules a self-message. It will be delivered back to the module
398
     * via receive() or handleMessage() at simulation time t. This method
399
     * is the way you can implement timers or timeouts. Timers can also
400
     * be cancelled via cancelEvent() (See below.)
401
     *
402
     * When the message is delivered at the module, you can call
403
     * <tt>msg->isSelfMessage()</tt> to tell it apart from messages arriving
404
     * from other modules. <tt>msg->getKind()</tt> can be used to further
405
     * classify it, or of you need to manage an unbounded number of timers,
406
     * you can set <tt>msg->getContextPointer()</tt> before scheduling to
407
     * point to the data structure the message belongs to -- this way
408
     * you can avoid having to search through lists or other data structures
409
     * to find out where a just-arrived self-message belongs.
410
     *
411
     * cancelEvent() can be used to cancel the self-message before it arrives.
412
     * This is useful for implementing timeouts: if the event occurs "in time"
413
     * (before timeout), the scheduled self-message can be cancelled.
414
     *
415
     * Given a cMessage pointer, you can check whether it is currently
416
     * scheduled by calling <tt>msg->isScheduled()</tt>. If it is scheduled,
417
     * you cannot schedule it again without calling cancelEvent() first.
418
     * However, after the message was delivered to the module or cancelled,
419
     * you can schedule it again -- so you can reuse the same message
420
     * object for timeouts over and over during the whole simulation.
421
     */
422
    int scheduleAt(simtime_t t, cMessage *msg);
423
424
    /**
425
     * Removes the given message from the future events. The message
426
     * needs to have been sent using the scheduleAt() function.
427
     * This function can be used to cancel a timer implemented with scheduleAt().
428
     * If the message is not currently scheduled, nothing happens.
429
     */
430
    cMessage *cancelEvent(cMessage *msg);
431
432
    /**
433
     * Invokes cancelEvent() on the message (in case it is scheduled), then
434
     * deletes it. A NULL pointer is also accepted, then the method does nothing.
435
     * This method is especially useful in simple module destructors, to dispose
436
     * of self-messages that the module has allocated.
437
     */
438
    void cancelAndDelete(cMessage *msg);
439
    //@}
440
441
    /** @name Receiving messages.
442
     *
443
     * These methods may only be invoked from activity()-based simple modules.
444
     */
445
    //@{
446
447
    /**
448
     * Remove the next message from the event queue and return a pointer
449
     * to it.
450
     */
451
    cMessage *receive();
452
453
    /**
454
     * Removes the next message from the event queue and returns a pointer
455
     * to it. If there is no message in the event
456
     * queue, the function waits with t timeout until a message will be
457
     * available. If the timeout expires and there is still no message
458
     * in the queue, the function returns NULL.
459
     */
460
    cMessage *receive(simtime_t timeout);
461
    //@}
462
463
    /** @name Waiting. */
464
    //@{
465
466
    /**
467
     * Waits for the given interval. (Some other simulators call this
468
     * functionality hold()).
469
     * It is intended for use only if you do not expect other messages
470
     * to arrive at the module during the wait period. To assert this,
471
     * it throws an exception if a message arrives during the wait.
472
     *
473
     * If you expect to receive messages during the call, you should use
474
     * waitAndEnqueue() instead.
475
     *
476
     * This function can only be used with activity(), but not with
477
     * handleMessage().
478
     */
479
    void wait(simtime_t time);
480
481
    /**
482
     * Waits for the given interval. The messages received during the wait
483
     * period are inserted into the queue passed as argument.
484
     *
485
     * This function can only be used with activity(), but not with
486
     * handleMessage().
487
     */
488
    void waitAndEnqueue(simtime_t time, cQueue *queue);
489
    //@}
490
491
    /** @name Stopping the module or the simulation. */
492
    //@{
493
    /**
494
     * Causes the whole simulation to stop. The implementation simply
495
     * throws a cTerminationException.
496
     */
497
    void endSimulation();
498
499
    /**
500
     * May only be invoked from activity()-based simple modules.
501
     * Execution of the simple module stops in this call, and any further
502
     * messages sent to module will cause a runtime error.
503
     */
504
    void halt();
505
506
    /**
507
     * Equivalent to <tt>throw cRuntimeError(<i>same argument list</i>)</tt>.
508
     */
509
    void error(const char *format,...) const;
510
    //@}
511
512
    /** @name Coroutine stack info. Useful only if module uses activity(). */
513
    //@{
514
515
    /**
516
     * Returns true if there was a stack overflow during execution of the
517
     * coroutine. (Not implemented for every coroutine package - see cCoroutine
518
     * documentation for more info.) If the module uses handleMessage(),
519
     * this method always returns false.
520
     *
521
     * @see cCoroutine
522
     */
523
    virtual bool hasStackOverflow() const;
524
525
    /**
526
     * Returns the stack size of the coroutine. If the module uses handleMessage(),
527
     * this method always returns 0.
528
     */
529
    virtual unsigned getStackSize() const;
530
531
    /**
532
     * Returns the amount of stack actually used by the coroutine.
533
     * (Not implemented for every coroutine package - see cCoroutine
534
     * documentation for more info.) If the module uses handleMessage(),
535
     * this method always returns 0.
536
     *
537
     * @see cCoroutine
538
     */
539
    virtual unsigned getStackUsage() const;
540 fbe00e73 Mirko Stoffers
541
  public: // Horizon
542
    /** @name User-implemented methods for asynchronous event handling. */
543
    //@{
544
    /**
545
     * Returns the duration of the given expanded event. Called by the event
546
     * scheduler to determine the overlapping of expanded events. The user may
547
     * perform any computation on the expanded event (except for deleting it)
548
     * to calculate the event duration.
549
     */
550
    virtual simtime_t getProcessingDelay(cMessage* msg)
551
    {
552
        return 0.0;
553
    }
554
555
    /*
556
     * By default non-expanded events are not executed in parallel. The
557
     * option "parallelize-zero-duration-events" globally enables or disables
558
     * parallel execution. This method allows users to overwrite either behavior
559
     * on a per module (and per event) basis. Should return true if parallel
560
     * execution is allowed, false otherwise.
561
     */
562
    virtual bool mayParallelize(cMessage* msg, simtime_t duration) const
563
    {
564
        return duration == SimTime::simTimeZero ? parZeroDur : true;
565
    }
566
    //}@
567
568
569
    /** @name Support methods for asynchronous event handling. */
570
    //@{
571
    /**
572
     * Returns the duration of the currently processed event.
573
     */
574
    simtime_t getCurrentProcessingDelay() const {
575
        return t_end - simTime();
576
    }
577
578
    /** @name Wrapper functions for state keeping inside a module. */
579
    //@{
580
    /**
581
     * INTERNAL: Wrapper for asynchronous message handling.
582
     */
583
    void callHandleAsyncMessage(cMessage* msg);
584
585
    /**
586
     * INTERNAL: Wrapper for synchronous message handling.
587
     */
588
    void callHandleMessage(cMessage* msg);
589
590
    /*
591
     * INTERNAL: Check if a worker thread is already busy inside this module
592
     * and if so, wait until the worker is done.
593
     */
594
    inline void waitIfBusy() {
595
        while (AO_load_full(&busy) == BUSY) {
596
            __asm__("pause");
597
        }
598
    }
599
600
    /*
601
     * INTERNAL: Indicate that a worker is busy inside this module.
602
     */
603
        inline void setBusy() {
604
                AO_store_full(&busy, BUSY);
605
        }
606
607
        /**
608
         * INTERNAL: Unset flag to indicate that a worker has finished.
609
         */
610
        inline void unsetBusy() {
611
                AO_store_full(&busy, NOT_BUSY);
612
        }
613
    //}@r
614
615
   //@}
616 01873262 Georg Kunz
};
617
618
NAMESPACE_END
619
620
621
#endif