Statistics
| Branch: | Revision:

root / include / casyncmodule.h @ 47c4b975

History | View | Annotate | Download (5.96 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
    // the module is idling, i.e., no event is current executed
50
    static const AO_t idleExecution = 0;
51

    
52
    // the module is currently executing a synchronous event
53
    static const AO_t syncExecution = 1;
54

    
55
    // the module is currently executing an asynchronous event
56
    static const AO_t asyncExecution = 2;
57

    
58
    // keeps the current state of the module
59
    AO_t execState;
60

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

    
64
    // shall zero duration events be executed in parallel
65
    bool parZeroDur;
66

    
67
    // no worker is active inside this module
68
    static const AO_t NOT_BUSY = 0;
69

    
70
    // a worker is active inside this module
71
    static const AO_t BUSY     = 1;
72

    
73
    // flag indicating that a thread is processing an event within this module
74
    AO_t busy;
75

    
76

    
77
  protected:
78
    // the central number generator of this module
79
    cNumberGenerator* numGen;
80

    
81

    
82
  public:
83
    /** @name Constructors and Destructors */
84
    //@{
85
    /**
86
     * Constructor
87
     */
88
    cAsyncModule(const char *name=NULL, cModule *parent=NULL, unsigned stacksize=0);
89

    
90
    /**
91
     * Destructor
92
     */
93
    virtual ~cAsyncModule();
94
    //}@
95

    
96

    
97
    /** @name User-implemented methods for asynchronous event handling. */
98
    //@{
99
    /**
100
     * Returns the duration of the given expanded event. Called by the event
101
     * scheduler to determine the overlapping of expanded events. The user may
102
     * perform any computation on the expanded event (except for deleting it)
103
     * to calculate the event duration.
104
     */
105
    virtual simtime_t getProcessingDelay(cMessage* msg)
106
    {
107
        return 0.0;
108
    }
109

    
110
    /*
111
     * By default non-expanded events are not executed in parallel. The
112
     * option "parallelize-zero-duration-events" globally enables or disables
113
     * parallel execution. This method allows users to overwrite either behavior
114
     * on a per module (and per event) basis. Should return true if parallel
115
     * execution is allowed, false otherwise.
116
     */
117
    virtual bool mayParallelize(cMessage* msg, simtime_t duration) const
118
    {
119
        return duration == SimTime::simTimeZero ? parZeroDur : true;
120
    }
121
    //}@
122

    
123

    
124
    /** @name Support methods for asynchronous event handling. */
125
    //@{
126
    /**
127
     * Returns the duration of the currently processed event.
128
     */
129
    simtime_t getCurrentProcessingDelay() const {
130
        return t_end - simTime();
131
    }
132

    
133
    /*
134
     * Returns true if the module supports parallel event execution.
135
     */
136
    virtual bool isAsyncModule() const {
137
            return true;
138
    }
139
    //}@
140

    
141

    
142
    /** @name Wrapper functions for state keeping inside a module. */
143
    //@{
144
    /**
145
     * INTERNAL: Wrapper for asynchronous message handling.
146
     */
147
    void callHandleAsyncMessage(cMessage* msg);
148

    
149
    /**
150
     * INTERNAL: Wrapper for synchronous message handling.
151
     */
152
    void callHandleMessage(cMessage* msg);
153

    
154
    /*
155
     * INTERNAL: Check if a worker thread is already busy inside this module
156
     * and if so, wait until the worker is done.
157
     */
158
    inline void waitIfBusy() {
159
        while (AO_load_full(&busy) == BUSY) {
160
            __asm__("pause");
161
        }
162
    }
163

    
164
    /*
165
     * INTERNAL: Indicate that a worker is busy inside this module.
166
     */
167
        inline void setBusy() {
168
                AO_store_full(&busy, BUSY);
169
        }
170

    
171
        /**
172
         * INTERNAL: Unset flag to indicate that a worker has finished.
173
         */
174
        inline void unsetBusy() {
175
                AO_store_full(&busy, NOT_BUSY);
176
        }
177
    //}@r
178

    
179

    
180
    /** @name Wrapper functions for the OMNeT++ API */
181
    //@{
182
    /**
183
     * @see cSimpleModule
184
     */
185
    virtual int scheduleAt(simtime_t t, cMessage *msg);
186

    
187
    /**
188
     * @see cSimpleModule
189
     */
190
    virtual int send(cMessage *msg, int gateid);
191

    
192
    /**
193
     * @see cSimpleModule
194
     */
195
    virtual int send(cMessage *msg, const char *gatename, int sn=-1);
196

    
197
    /**
198
     * @see cSimpleModule
199
     */
200
    virtual int send(cMessage *msg, cGate *outputgate);
201

    
202
    /**
203
     * @see cSimpleModule
204
     */
205
    virtual int sendDelayed(cMessage *msg, simtime_t delay, int gateid);
206

    
207
    /**
208
     * @see cSimpleModule
209
     */
210
    virtual int sendDelayed(cMessage *msg, simtime_t delay, const char *gatename, int sn=-1);
211

    
212
    /**
213
     * @see cSimpleModule
214
     */
215
    virtual int sendDelayed(cMessage *msg, simtime_t delay, cGate *outputgate);
216

    
217
    /**
218
     * @see cSimpleModule
219
     */
220
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cModule *mod, int inputgateid);
221

    
222
    /**
223
     * @see cSimpleModule
224
     */
225
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cModule *mod, const char *inputgatename, int sn=-1);
226

    
227
    /**
228
     * @see cSimpleModule
229
     */
230
    virtual int sendDirect(cMessage *msg, simtime_t delay, simtime_t duration, cGate *inputgate);
231
    //}@
232
};
233

    
234
#endif /* __CASYNCMODULE_H */