Statistics
| Branch: | Revision:

root / include / casyncmodule.h @ ffa9279f

History | View | Annotate | Download (6.42 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

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

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

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

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

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

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

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

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

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

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

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

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

    
82
    //
83
    unsigned int executionOrderId;
84

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

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

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

    
98
  protected:
99

    
100
  public:
101
    /** @name Constructors and Destructors */
102
    //@{
103
    /**
104
     * Constructor
105
     */
106
    cAsyncModule(const char *name=NULL, cModule *parent=NULL, unsigned stacksize=0);
107

    
108
    /**
109
     * Destructor
110
     */
111
    virtual ~cAsyncModule();
112
    //}@
113

    
114

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

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

    
145

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

    
155
    /*
156
     * Returns true if the module supports parallel event execution.
157
     */
158
    virtual bool isAsyncModule() const {
159
            return true;
160
    }
161
    //}@
162

    
163

    
164
    /** @name Wrapper functions for state keeping inside a module. */
165
    //@{
166
    /**
167
     * INTERNAL: Wrapper for asynchronous message handling.
168
     */
169
    void callHandleAsyncMessage(cMessage* msg);
170

    
171
    /**
172
     * INTERNAL: Wrapper for synchronous message handling.
173
     */
174
    void callHandleMessage(cMessage* msg);
175

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

    
186
    /*
187
     * INTERNAL: Indicate that a worker is busy inside this module.
188
     */
189
        inline void setBusy() {
190
                AO_store_full(&busy, BUSY);
191
        }
192

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

    
201

    
202
    /** @name Wrapper functions for the OMNeT++ API */
203
    //@{
204
    /**
205
     * @see cSimpleModule
206
     */
207
    virtual int scheduleAt(simtime_t t, cMessage *msg);
208

    
209
    /**
210
     * @see cSimpleModule
211
     */
212
    virtual int send(cMessage *msg, int gateid);
213

    
214
    /**
215
     * @see cSimpleModule
216
     */
217
    virtual int send(cMessage *msg, const char *gatename, int sn=-1);
218

    
219
    /**
220
     * @see cSimpleModule
221
     */
222
    virtual int send(cMessage *msg, cGate *outputgate);
223

    
224
    /**
225
     * @see cSimpleModule
226
     */
227
    virtual int sendDelayed(cMessage *msg, simtime_t delay, int gateid);
228

    
229
    /**
230
     * @see cSimpleModule
231
     */
232
    virtual int sendDelayed(cMessage *msg, simtime_t delay, const char *gatename, int sn=-1);
233

    
234
    /**
235
     * @see cSimpleModule
236
     */
237
    virtual int sendDelayed(cMessage *msg, simtime_t delay, cGate *outputgate);
238

    
239
    /**
240
     * @see cSimpleModule
241
     */
242
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cModule *mod, int inputgateid);
243

    
244
    /**
245
     * @see cSimpleModule
246
     */
247
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cModule *mod, const char *inputgatename, int sn=-1);
248

    
249
    /**
250
     * @see cSimpleModule
251
     */
252
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cGate *inputgate);
253
    //}@
254

    
255
};
256

    
257
#endif /* __CASYNCMODULE_H */