Statistics
| Branch: | Revision:

root / include / casyncmodule.h @ 77cb9420

History | View | Annotate | Download (8.94 KB)

1
//==========================================================================
2
//   CASYNCMODULE.H  -  header for
3
//                     Horizon/OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//
7
//  Declaration of the following classes:
8
//    cAsyncModule  : base for asynchronous event handing in simple module objects
9
//
10
//==========================================================================
11

    
12
/*--------------------------------------------------------------*
13
  Copyright (C) 2009 Georg Kunz
14

15
  This file is distributed WITHOUT ANY WARRANTY. See the file
16
  `license' for details on this and other legal matters.
17
*--------------------------------------------------------------*/
18

    
19
#ifndef __CASYNCMODULE_H
20
#define __CASYNCMODULE_H
21

    
22
#include <pthread.h>
23
#include <semaphore.h>
24

    
25
#include "csimplemodule.h"
26
#include "cmessage.h"
27
#include "cnumgen.h"
28

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

    
35
/**
36
 * New base class for all modules that handle expanded events for asynchronous
37
 * (parallel) execution. It provides new methods for parallel event handling
38
 * and wrappers of the default API.
39
 *
40
 * @see cSimpleModule
41
 *
42
 * @ingroup Horizon
43
 */
44
class cAsyncMessage;
45

    
46
class SIM_API cAsyncModule : public cSimpleModule
47
{
48
  private:
49

    
50
    // the two different execution states: either handleMessage is called
51
    // synchronously by the scheduler or asynchronously (to the scheduler)
52
    // by a worker thread
53
    enum ExecutionStates
54
    {
55
        synchronous,
56
        asynchronous
57
    };
58

    
59
    // current state of execution
60
    ExecutionStates executionState;
61

    
62
    // new messages may only be scheduled with timestamps >= this value
63
    simtime_t t_end;
64

    
65
    // priority of the current event
66
    short currentEventPriority;
67

    
68
    // shall zero duration events be executed in parallel
69
    bool parZeroDur;
70

    
71
    // no worker is active inside this module
72
    static const AO_t NOT_BUSY = 0;
73

    
74
    // a worker is active inside this module
75
    static const AO_t BUSY     = 1;
76

    
77
    // flag indicating that a thread is processing an event within this module
78
    AO_t busy;
79

    
80
    // how many messages did a given event send?
81
    unsigned int scheduledMessageCount;
82

    
83
    //
84
    unsigned int executionOrderId;
85

    
86
    // current simulation time within this module
87
    simtime_t now;
88

    
89
    /**
90
     * update meta data needed for event execution
91
     */
92
    void prepareHandleMessage(cMessage* msg);
93

    
94
    /**
95
     * set extended meta data of a message upon sending.
96
     */
97
    void setMessageMetaData(cMessage* msg);
98

    
99
  protected:
100
    // the central number generator of this module
101
    cNumberGenerator* numGen;
102

    
103

    
104
  public:
105
    /** @name Constructors and Destructors */
106
    //@{
107
    /**
108
     * Constructor
109
     */
110
    cAsyncModule(const char *name=NULL, cModule *parent=NULL, unsigned stacksize=0);
111

    
112
    /**
113
     * Destructor
114
     */
115
    virtual ~cAsyncModule();
116
    //}@
117

    
118

    
119
    /** @name User-implemented methods for asynchronous event handling. */
120
    //@{
121
    /**
122
     * Returns the duration of the given expanded event. Called by the event
123
     * scheduler to determine the overlapping of expanded events. The user may
124
     * perform any computation on the expanded event (except for deleting it)
125
     * to calculate the event duration.
126
     */
127
    virtual simtime_t getProcessingDelay(cMessage* msg)
128
    {
129
        return 0.0;
130
    }
131

    
132
    /*
133
     * By default non-expanded events are not executed in parallel. The
134
     * option "parallelize-zero-duration-events" globally enables or disables
135
     * parallel execution. This method allows users to overwrite either behavior
136
     * on a per module (and per event) basis. Should return true if parallel
137
     * execution is allowed, false otherwise.
138
     */
139
    virtual bool mayParallelize(cMessage* msg, simtime_t duration) const
140
    {
141
        return duration == SimTime::simTimeZero ? parZeroDur : true;
142
    }
143
    /*
144
     * Initializes the local RNGs according to config options read from ini
145
     */
146
    void initLocalRNGs();
147
    //}@
148

    
149

    
150
    /** @name Support methods for asynchronous event handling. */
151
    //@{
152
    /**
153
     * Returns the duration of the currently processed event.
154
     */
155
    simtime_t getCurrentProcessingDelay() const {
156
        return t_end - simTime();
157
    }
158

    
159
    /*
160
     * Returns true if the module supports parallel event execution.
161
     */
162
    virtual bool isAsyncModule() const {
163
            return true;
164
    }
165
    //}@
166

    
167

    
168
    /** @name Wrapper functions for state keeping inside a module. */
169
    //@{
170
    /**
171
     * INTERNAL: Wrapper for asynchronous message handling.
172
     */
173
    void callHandleAsyncMessage(cMessage* msg);
174

    
175
    /**
176
     * INTERNAL: Wrapper for synchronous message handling.
177
     */
178
    void callHandleMessage(cMessage* msg);
179

    
180
    /*
181
     * INTERNAL: Check if a worker thread is already busy inside this module
182
     * and if so, wait until the worker is done.
183
     */
184
    inline void waitIfBusy() {
185
        while (AO_load_full(&busy) == BUSY) {
186
            __asm__("pause");
187
        }
188
    }
189

    
190
    /*
191
     * INTERNAL: Indicate that a worker is busy inside this module.
192
     */
193
        inline void setBusy() {
194
                AO_store_full(&busy, BUSY);
195
        }
196

    
197
        /**
198
         * INTERNAL: Unset flag to indicate that a worker has finished.
199
         */
200
        inline void unsetBusy() {
201
                AO_store_full(&busy, NOT_BUSY);
202
        }
203
    //}@r
204

    
205

    
206
    /** @name Wrapper functions for the OMNeT++ API */
207
    //@{
208
    /**
209
     * @see cSimpleModule
210
     */
211
    virtual int scheduleAt(simtime_t t, cMessage *msg);
212

    
213
    /**
214
     * @see cSimpleModule
215
     */
216
    virtual int send(cMessage *msg, int gateid);
217

    
218
    /**
219
     * @see cSimpleModule
220
     */
221
    virtual int send(cMessage *msg, const char *gatename, int sn=-1);
222

    
223
    /**
224
     * @see cSimpleModule
225
     */
226
    virtual int send(cMessage *msg, cGate *outputgate);
227

    
228
    /**
229
     * @see cSimpleModule
230
     */
231
    virtual int sendDelayed(cMessage *msg, simtime_t delay, int gateid);
232

    
233
    /**
234
     * @see cSimpleModule
235
     */
236
    virtual int sendDelayed(cMessage *msg, simtime_t delay, const char *gatename, int sn=-1);
237

    
238
    /**
239
     * @see cSimpleModule
240
     */
241
    virtual int sendDelayed(cMessage *msg, simtime_t delay, cGate *outputgate);
242

    
243
    /**
244
     * @see cSimpleModule
245
     */
246
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cModule *mod, int inputgateid);
247

    
248
    /**
249
     * @see cSimpleModule
250
     */
251
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cModule *mod, const char *inputgatename, int sn=-1);
252

    
253
    /**
254
     * @see cSimpleModule
255
     */
256
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cGate *inputgate);
257
    //}@
258

    
259

    
260
    /*
261
     *
262
     * Wrapper methods for numberGenerator Method calls
263
     *
264
     */
265

    
266
    inline double uniform(double a, double b, int rng=0) {
267
        return numGen->uniform(a,b,rng);
268
    }
269

    
270
    inline double exponential(double mean, int rng=0) {
271
        return numGen->exponential(mean, rng);
272
    }
273

    
274
    inline double normal(double mean, double stddev, int rng=0) {
275
        return numGen->normal(mean,stddev, rng);
276
    }
277

    
278
    inline double truncnormal(double mean, double stddev, int rng=0) {
279
        return numGen->truncnormal(mean,stddev, rng);
280
    }
281

    
282
    inline double gamma_d(double alpha, double theta, int rng=0) {
283
        return numGen->gamma_d(alpha, theta, rng);
284
    }
285

    
286
    inline double beta(double alpha1, double alpha2, int rng=0) {
287
        return numGen->beta(alpha1,alpha2, rng);
288
    }
289

    
290
    inline double erlang_k(unsigned int k, double mean, int rng=0) {
291
        return numGen->erlang_k(k, mean, rng);
292
    }
293

    
294
    inline double chi_square(unsigned int k, int rng=0) {
295
        return numGen->chi_square(k, rng);
296
    }
297

    
298
    inline double student_t(unsigned int i, int rng=0) {
299
        return numGen->student_t(i, rng);
300
    }
301

    
302
    inline double cauchy(double a, double b, int rng=0) {
303
        return numGen->cauchy(a,b, rng);
304
    }
305

    
306
    inline double triang(double a, double b, double c, int rng=0) {
307
        return numGen->triang(a,b,c, rng);
308
    }
309

    
310
    inline double lognormal(double m, double w, int rng=0) {
311
        return numGen->lognormal(m,w, rng);
312
    }
313

    
314
    inline double weibull(double a, double b, int rng=0) {
315
        return numGen->weibull(a,b, rng);
316
    }
317

    
318
    inline double pareto_shifted(double a, double b, double c, int rng=0) {
319
        return numGen->pareto_shifted(a,b,c, rng);
320
    }
321

    
322
    inline int intuniform(int a, int b, int rng=0) {
323
        return numGen->intuniform(a,b, rng);
324
    }
325

    
326
    inline int bernoulli(double p, int rng=0) {
327
        return numGen->bernoulli(p, rng);
328
    }
329

    
330
    inline int binomial(int n, double p, int rng=0) {
331
        return numGen->binomial(n,p, rng);
332
    }
333

    
334
    inline int geometric(double p, int rng=0) {
335
        return numGen->geometric(p, rng);
336
    }
337

    
338
    inline int negbinomial(int n, double p, int rng=0) {
339
        return numGen->negbinomial(n,p, rng);
340
    }
341

    
342
    inline int poisson(double lambda, int rng=0) {
343
        return numGen->poisson(lambda, rng);
344
    }
345

    
346
    inline long intrand(long r) {
347
        return numGen->intrand(r);
348
    }
349

    
350
    inline double dblrand() {
351
        return numGen->dblrand();
352
    }
353

    
354
};
355

    
356
#endif /* __CASYNCMODULE_H */