Project

General

Profile

Statistics
| Branch: | Revision:

root / include / casyncmodule.h @ b781545c

History | View | Annotate | Download (6.46 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, public cNumberGenerator
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

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

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

    
115

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

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

    
146

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

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

    
164

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

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

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

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

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

    
202

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

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

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

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

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

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

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

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

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

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

    
256
};
257

    
258
#endif /* __CASYNCMODULE_H */