Statistics
| Branch: | Revision:

root / include / csimplemodule.h @ fbe00e73

History | View | Annotate | Download (21.4 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
  Copyright (C) 2009 Georg Kunz
16

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
#include <pthread.h>
25
#include <semaphore.h>
26

    
27
#include "cmodule.h"
28
#include "cnumgen.h"
29

    
30
#ifdef ATOMIC_OPS_DEBUG
31
        #include "catomicopsdebug.h"
32
#else
33
        #include <atomic_ops.h>
34
#endif
35

    
36
NAMESPACE_BEGIN
37

    
38
class cQueue;
39
class cCoroutine;
40

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

    
80
  private:
81
    enum {
82
        FL_USESACTIVITY = 512,   // uses activity() or handleMessage()
83
        FL_ISTERMINATED = 1024,  // for both activity and handleMessage modules
84
        FL_STACKALREADYUNWOUND = 2048, // only for activity modules
85
    };
86
    cMessage *timeoutmsg;   // msg used in wait() and receive() with timeout
87
    cCoroutine *coroutine;
88

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

    
92
  private: // Horizon
93
    // the two different execution states: either handleMessage is called
94
    // synchronously by the scheduler or asynchronously (to the scheduler)
95
    // by a worker thread
96
    enum ExecutionStates
97
    {
98
        synchronous,
99
        asynchronous
100
    };
101

    
102
    // current state of execution
103
    ExecutionStates executionState;
104

    
105
    // new messages may only be scheduled with timestamps >= this value
106
    simtime_t t_end;
107

    
108
    // priority of the current event
109
    short currentEventPriority;
110

    
111
    // shall zero duration events be executed in parallel
112
    bool parZeroDur;
113

    
114
    // no worker is active inside this module
115
    static const AO_t NOT_BUSY = 0;
116

    
117
    // a worker is active inside this module
118
    static const AO_t BUSY     = 1;
119

    
120
    // flag indicating that a thread is processing an event within this module
121
    AO_t busy;
122

    
123
    // how many messages did a given event send?
124
    unsigned int scheduledMessageCount;
125

    
126
    //
127
    unsigned int executionOrderId;
128

    
129
    // current simulation time within this module
130
    simtime_t now;
131

    
132
    /**
133
     * update meta data needed for event execution
134
     */
135
    void prepareHandleMessage(cMessage* msg);
136

    
137
    /**
138
     * set extended meta data of a message upon sending.
139
     */
140
    void setMessageMetaData(cMessage* msg);
141

    
142
  private:
143
    // internal use
144
    static void activate(void *p);
145

    
146
  protected:
147
    // internal use
148
    virtual void arrived(cMessage *msg, cGate *ongate, simtime_t t);
149

    
150
    // internal: sets the module id.
151
    virtual void setId(int n);
152

    
153
  protected:
154
    /** @name Hooks for defining module behavior.
155
     *
156
     * Exactly one of activity() and handleMessage() must be redefined
157
     * by the user to add functionality to the simple module. See the
158
     * manual for detailed guidance on how use to these two methods.
159
     *
160
     * These methods are made protected because they shouldn't be called
161
     * directly from outside.
162
     */
163
    //@{
164

    
165
    /**
166
     * Should be redefined to contain the module activity function.
167
     * For several good reasons, you should prefer handleMessage() to activity().
168
     * This default implementation issues an error message (throws cRuntimeError).
169
     */
170
    virtual void activity();
171

    
172
    /**
173
     * Should be redefined to contain the module's message handling function.
174
     * This default implementation issues an error message (throws cRuntimeError).
175
     */
176
    virtual void handleMessage(cMessage *msg);
177
    //@}
178

    
179
  public:
180
    /** @name Constructors, destructor, assignment. */
181
    //@{
182
    /**
183
     * Constructor. Note that module objects should not be created directly,
184
     * only via their cModuleType objects. See cModule constructor for more info.
185
     * The stacksize parameter should only be used with simple modules using
186
     * activity().
187
     */
188
    cSimpleModule(unsigned stacksize = 0);
189

    
190
    /**
191
     * COMPATIBILITY. This constructor is only provided to make it possible
192
     * to write simple modules that do not use the Module_Class_Members
193
     * macro and can also be compiled with OMNeT++ versions earlier than
194
     * 3.2. The first two args are unused in this and later versions.
195
     */
196
    cSimpleModule(const char *dummy1, cModule *dummy2, unsigned stacksize);
197

    
198
    /**
199
     * Destructor.
200
     */
201
    virtual ~cSimpleModule();
202
    //@}
203

    
204
    /** @name Redefined cObject member functions. */
205
    //@{
206
    /**
207
     * Produces a one-line description of the object's contents.
208
     * See cObject for more details.
209
     */
210
    virtual std::string info() const;
211

    
212
    /**
213
     * Calls v->visit(this) for each contained object.
214
     * See cObject for more details.
215
     */
216
    virtual void forEachChild(cVisitor *v);
217
    //@}
218

    
219
    /** @name Redefined cModule functions. */
220
    //@{
221

    
222
    /**
223
     * Creates a starting message for the module.
224
     */
225
    virtual void scheduleStart(simtime_t t);
226

    
227
    /**
228
     * Deletes the module and all its (dynamically created) submodules.
229
     *
230
     * A running module can also delete itself. When an activity()-based
231
     * simple module deletes itself from within its activity(), the
232
     * deleteModule() call will not return (it throws an exception which
233
     * gets caught by the simulation kernel, and the simulation kernel
234
     * will delete the module).
235
     *
236
     * When a handleMessage()-based module deletes itself, the deleteModule()
237
     * returns normally -- then, of course, the code should not try to
238
     * access data members or functions of the deleted module, an should
239
     * return as soon as possible.
240
     */
241
    virtual void deleteModule();
242
    //@}
243

    
244
    /** @name Information about the module. */
245
    //@{
246

    
247
    /**
248
     * Returns the event handling scheme: activity() or handleMessage().
249
     */
250
    bool usesActivity() const  {return flags&FL_USESACTIVITY;}
251

    
252
    /**
253
     * Returns true if the module has already terminated, by having called end()
254
     * or returning from the activity() method.
255
     */
256
    bool isTerminated() const {return flags&FL_ISTERMINATED;}
257
    //@}
258

    
259
    /** @name Debugging aids. */
260
    //@{
261
    /**
262
     * To be called from module functions. Outputs textual information
263
     * about all objects of the simulation (including the objects created
264
     * in module functions by the user!) into the snapshot file. The
265
     * output is detailed enough to be used for debugging the simulation:
266
     * by regularly calling snapshot(), one can trace how the
267
     * values of variables, objects changed over the simulation. The
268
     * arguments: label is a string that will appear in the
269
     * output file; obj is the object whose inside is of interest.
270
     * By default, the whole simulation (all modules etc) will be written
271
     * out.
272
     *
273
     * Tkenv also supports making snapshots manually, from menu.
274
     *
275
     * See also class cWatch and the WATCH() macro.
276
     */
277
    bool snapshot(cObject *obj=NULL, const char *label=NULL);
278
    //@}
279

    
280
    /** @name Message sending. */
281
    //@{
282

    
283
    /**
284
     * Sends a message through the gate given with its ID.
285
     */
286
    int send(cMessage *msg, int gateid);
287

    
288
    /**
289
     * Sends a message through the gate given with its name and index
290
     * (if multiple gate).
291
     */
292
    int send(cMessage *msg, const char *gatename, int gateindex=-1);
293

    
294
    /**
295
     * Sends a message through the gate given with its pointer.
296
     */
297
    int send(cMessage *msg, cGate *outputgate);
298

    
299
    /**
300
     * Delayed sending. Sends a message through the gate given with
301
     * its index as if it was sent delay seconds later.
302
     */
303
    int sendDelayed(cMessage *msg, simtime_t delay, int gateid);
304

    
305
    /**
306
     * Delayed sending. Sends a message through the gate given with
307
     * its name and index (if multiple gate) as if it was sent delay
308
     * seconds later.
309
     */
310
    int sendDelayed(cMessage *msg, simtime_t delay, const char *gatename, int gateindex=-1);
311

    
312
    /**
313
     * Sends a message through the gate given with its pointer as if
314
     * it was sent delay seconds later.
315
     */
316
    int sendDelayed(cMessage *msg, simtime_t delay, cGate *outputgate);
317

    
318
    /**
319
     * Sends a message directly to another module, with zero propagation delay
320
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
321
     * for a more detailed description.
322
     */
323
    int sendDirect(cMessage *msg, cModule *mod, const char *inputGateName, int gateIndex=-1);
324

    
325
    /**
326
     * Sends a message directly to another module, with zero propagation delay
327
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
328
     * for a more detailed description.
329
     */
330
    int sendDirect(cMessage *msg, cModule *mod, int inputGateId);
331

    
332
    /**
333
     * Sends a message directly to another module, with zero propagation delay
334
     * and duration. See sendDirect(cMessage *, simtime_t, simtime_t, cGate *)
335
     * for a more detailed description.
336
     */
337
    int sendDirect(cMessage *msg, cGate *inputGate);
338

    
339
    /**
340
     * Sends a message directly to another module.
341
     * See sendDirect(cMessage *, simtime_t, simtime_t, cGate *) for a more
342
     * detailed description.
343
     */
344
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cModule *mod, const char *inputGateName, int gateIndex=-1);
345

    
346
    /**
347
     * See sendDirect(cMessage *, simtime_t, simtime_t, cGate *) for a more
348
     * detailed description.
349
     */
350
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cModule *mod, int inputGateId);
351

    
352
    /**
353
     * Send a message directly to another module.
354
     *
355
     * If the gate is further connected (i.e. getNextGate()!=NULL), the
356
     * message will follow the connections that start at that gate.
357
     * For example, when sending to an input gate of a compound module,
358
     * the message will follow the connections to the inside of the compound module.
359
     *
360
     * It is permitted to send to an output gate, which will also cause the
361
     * message to follow the connections starting at that gate.
362
     * This can be useful, for example, when several submodules are sending
363
     * to a single output gate of their parent module.
364
     *
365
     * It is not permitted to send to a gate of a compound module which is not
366
     * further connected (i.e. getNextGate()==NULL), as this would cause the message
367
     * to arrive at a compound module.
368
     *
369
     * Also, it is not permitted to send to a gate which is otherwise connected
370
     * i.e. where getPreviousGate()!=NULL. This means that modules MUST have
371
     * dedicated gates for receiving via sendDirect(). You cannot have a gate
372
     * which receives messages via both connections and sendDirect().
373
     *
374
     * When a nonzero duration is given, that signifies the duration of the packet
375
     * transmission, that is, the time difference between the transmission (or
376
     * reception) of the start of the packet and that of the end of the packet.
377
     * The destination module can choose whether it wants the simulation kernel
378
     * to deliver the packet object to it at the start or at the end of the
379
     * reception. The default is the latter; the module can change it by calling
380
     * setDeliverOnReceptionStart() on the final input gate (that is, on
381
     * inputGate->getPathEndGate()). setDeliverOnReceptionStart() needs to be
382
     * called in advance, for example in the initialize() method of the module.
383
     * When a module receives a packet, it can call the isReceptionStart() and
384
     * getDuration() methods on the packet to find out whether it represents
385
     * the start or the end of the reception, and the duration of the
386
     * transmission.
387
     *
388
     * For messages that are not packets (i.e. not subclassed from cPacket),
389
     * the duration parameter is ignored, that is, it will be taken as zero.
390
     */
391
    int sendDirect(cMessage *msg, simtime_t propagationDelay, simtime_t duration, cGate *inputGate);
392
    //@}
393

    
394
    /** @name Self-messages. */
395
    //@{
396

    
397
    /**
398
     * Schedules a self-message. It will be delivered back to the module
399
     * via receive() or handleMessage() at simulation time t. This method
400
     * is the way you can implement timers or timeouts. Timers can also
401
     * be cancelled via cancelEvent() (See below.)
402
     *
403
     * When the message is delivered at the module, you can call
404
     * <tt>msg->isSelfMessage()</tt> to tell it apart from messages arriving
405
     * from other modules. <tt>msg->getKind()</tt> can be used to further
406
     * classify it, or of you need to manage an unbounded number of timers,
407
     * you can set <tt>msg->getContextPointer()</tt> before scheduling to
408
     * point to the data structure the message belongs to -- this way
409
     * you can avoid having to search through lists or other data structures
410
     * to find out where a just-arrived self-message belongs.
411
     *
412
     * cancelEvent() can be used to cancel the self-message before it arrives.
413
     * This is useful for implementing timeouts: if the event occurs "in time"
414
     * (before timeout), the scheduled self-message can be cancelled.
415
     *
416
     * Given a cMessage pointer, you can check whether it is currently
417
     * scheduled by calling <tt>msg->isScheduled()</tt>. If it is scheduled,
418
     * you cannot schedule it again without calling cancelEvent() first.
419
     * However, after the message was delivered to the module or cancelled,
420
     * you can schedule it again -- so you can reuse the same message
421
     * object for timeouts over and over during the whole simulation.
422
     */
423
    int scheduleAt(simtime_t t, cMessage *msg);
424

    
425
    /**
426
     * Removes the given message from the future events. The message
427
     * needs to have been sent using the scheduleAt() function.
428
     * This function can be used to cancel a timer implemented with scheduleAt().
429
     * If the message is not currently scheduled, nothing happens.
430
     */
431
    cMessage *cancelEvent(cMessage *msg);
432

    
433
    /**
434
     * Invokes cancelEvent() on the message (in case it is scheduled), then
435
     * deletes it. A NULL pointer is also accepted, then the method does nothing.
436
     * This method is especially useful in simple module destructors, to dispose
437
     * of self-messages that the module has allocated.
438
     */
439
    void cancelAndDelete(cMessage *msg);
440
    //@}
441

    
442
    /** @name Receiving messages.
443
     *
444
     * These methods may only be invoked from activity()-based simple modules.
445
     */
446
    //@{
447

    
448
    /**
449
     * Remove the next message from the event queue and return a pointer
450
     * to it.
451
     */
452
    cMessage *receive();
453

    
454
    /**
455
     * Removes the next message from the event queue and returns a pointer
456
     * to it. If there is no message in the event
457
     * queue, the function waits with t timeout until a message will be
458
     * available. If the timeout expires and there is still no message
459
     * in the queue, the function returns NULL.
460
     */
461
    cMessage *receive(simtime_t timeout);
462
    //@}
463

    
464
    /** @name Waiting. */
465
    //@{
466

    
467
    /**
468
     * Waits for the given interval. (Some other simulators call this
469
     * functionality hold()).
470
     * It is intended for use only if you do not expect other messages
471
     * to arrive at the module during the wait period. To assert this,
472
     * it throws an exception if a message arrives during the wait.
473
     *
474
     * If you expect to receive messages during the call, you should use
475
     * waitAndEnqueue() instead.
476
     *
477
     * This function can only be used with activity(), but not with
478
     * handleMessage().
479
     */
480
    void wait(simtime_t time);
481

    
482
    /**
483
     * Waits for the given interval. The messages received during the wait
484
     * period are inserted into the queue passed as argument.
485
     *
486
     * This function can only be used with activity(), but not with
487
     * handleMessage().
488
     */
489
    void waitAndEnqueue(simtime_t time, cQueue *queue);
490
    //@}
491

    
492
    /** @name Stopping the module or the simulation. */
493
    //@{
494
    /**
495
     * Causes the whole simulation to stop. The implementation simply
496
     * throws a cTerminationException.
497
     */
498
    void endSimulation();
499

    
500
    /**
501
     * May only be invoked from activity()-based simple modules.
502
     * Execution of the simple module stops in this call, and any further
503
     * messages sent to module will cause a runtime error.
504
     */
505
    void halt();
506

    
507
    /**
508
     * Equivalent to <tt>throw cRuntimeError(<i>same argument list</i>)</tt>.
509
     */
510
    void error(const char *format,...) const;
511
    //@}
512

    
513
    /** @name Coroutine stack info. Useful only if module uses activity(). */
514
    //@{
515

    
516
    /**
517
     * Returns true if there was a stack overflow during execution of the
518
     * coroutine. (Not implemented for every coroutine package - see cCoroutine
519
     * documentation for more info.) If the module uses handleMessage(),
520
     * this method always returns false.
521
     *
522
     * @see cCoroutine
523
     */
524
    virtual bool hasStackOverflow() const;
525

    
526
    /**
527
     * Returns the stack size of the coroutine. If the module uses handleMessage(),
528
     * this method always returns 0.
529
     */
530
    virtual unsigned getStackSize() const;
531

    
532
    /**
533
     * Returns the amount of stack actually used by the coroutine.
534
     * (Not implemented for every coroutine package - see cCoroutine
535
     * documentation for more info.) If the module uses handleMessage(),
536
     * this method always returns 0.
537
     *
538
     * @see cCoroutine
539
     */
540
    virtual unsigned getStackUsage() const;
541

    
542
  public: // Horizon
543
    /** @name User-implemented methods for asynchronous event handling. */
544
    //@{
545
    /**
546
     * Returns the duration of the given expanded event. Called by the event
547
     * scheduler to determine the overlapping of expanded events. The user may
548
     * perform any computation on the expanded event (except for deleting it)
549
     * to calculate the event duration.
550
     */
551
    virtual simtime_t getProcessingDelay(cMessage* msg)
552
    {
553
        return 0.0;
554
    }
555

    
556
    /*
557
     * By default non-expanded events are not executed in parallel. The
558
     * option "parallelize-zero-duration-events" globally enables or disables
559
     * parallel execution. This method allows users to overwrite either behavior
560
     * on a per module (and per event) basis. Should return true if parallel
561
     * execution is allowed, false otherwise.
562
     */
563
    virtual bool mayParallelize(cMessage* msg, simtime_t duration) const
564
    {
565
        return duration == SimTime::simTimeZero ? parZeroDur : true;
566
    }
567
    /*
568
     * Initializes the local RNGs according to config options read from ini
569
     */
570
    void initLocalRNGs();
571
    //}@
572

    
573

    
574
    /** @name Support methods for asynchronous event handling. */
575
    //@{
576
    /**
577
     * Returns the duration of the currently processed event.
578
     */
579
    simtime_t getCurrentProcessingDelay() const {
580
        return t_end - simTime();
581
    }
582

    
583
    /** @name Wrapper functions for state keeping inside a module. */
584
    //@{
585
    /**
586
     * INTERNAL: Wrapper for asynchronous message handling.
587
     */
588
    void callHandleAsyncMessage(cMessage* msg);
589

    
590
    /**
591
     * INTERNAL: Wrapper for synchronous message handling.
592
     */
593
    void callHandleMessage(cMessage* msg);
594

    
595
    /*
596
     * INTERNAL: Check if a worker thread is already busy inside this module
597
     * and if so, wait until the worker is done.
598
     */
599
    inline void waitIfBusy() {
600
        while (AO_load_full(&busy) == BUSY) {
601
            __asm__("pause");
602
        }
603
    }
604

    
605
    /*
606
     * INTERNAL: Indicate that a worker is busy inside this module.
607
     */
608
        inline void setBusy() {
609
                AO_store_full(&busy, BUSY);
610
        }
611

    
612
        /**
613
         * INTERNAL: Unset flag to indicate that a worker has finished.
614
         */
615
        inline void unsetBusy() {
616
                AO_store_full(&busy, NOT_BUSY);
617
        }
618
    //}@r
619

    
620
   //@}
621
};
622

    
623
NAMESPACE_END
624

    
625

    
626
#endif
627