version 2.8
gevent.h
Go to the documentation of this file.
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.org/license.html
6  */
7 
8 /**
9  * @file src/gevent/gevent.h
10  *
11  * @addtogroup GEVENT
12  *
13  * @brief Module to build a complete many-to-many event system
14  *
15  * @details GEVENT provides a simple to use but yet powerful event
16  * system.
17  *
18  * @pre GFX_USE_GEVENT must be set to TRUE in your gfxconf.h
19  *
20  * @{
21  */
22 #ifndef _GEVENT_H
23 #define _GEVENT_H
24 
25 #include "../../gfx.h"
26 
27 #if GFX_USE_GEVENT || defined(__DOXYGEN__)
28 
29 /*===========================================================================*/
30 /* Type definitions */
31 /*===========================================================================*/
32 
33 typedef uint16_t GEventType;
34  #define GEVENT_NULL 0x0000 // Null Event - Do nothing
35  #define GEVENT_EXIT 0x0001 // The listener is being forced to exit (someone is destroying the listener)
36 
37  /* Other event types are allocated in ranges in their respective include files */
38  #define GEVENT_GINPUT_FIRST 0x0100 // GINPUT events range from 0x0100 to 0x01FF
39  #define GEVENT_GWIN_FIRST 0x0200 // GWIN events range from 0x0200 to 0x02FF
40  #define GEVENT_GADC_FIRST 0x0300 // GADC events range from 0x0300 to 0x033F
41  #define GEVENT_GAUDIO_FIRST 0x0340 // GAUDIO events range from 0x0340 to 0x037F
42  #define GEVENT_USER_FIRST 0x8000 // Any application defined events start at 0x8000
43 
44 // This object can be typecast to any GEventXxxxx type to allow any sub-system (or the application) to create events.
45 // The prerequisite is that the new status structure type starts with a field named 'type' of type 'GEventType'.
46 // The total status structure also must not exceed GEVENT_MAXIMUM_SIZE bytes.
47 // For example, this is used by GWIN button events, GINPUT data streams etc.
48 typedef union GEvent_u {
49  GEventType type; // The type of this event
50  char pad[GEVENT_MAXIMUM_SIZE]; // This is here to allow static initialisation of GEventObject's in the application.
51 } GEvent;
52 
53 // A special callback function
54 typedef void (*GEventCallbackFn)(void *param, GEvent *pe);
55 
56 // The Listener Object
57 typedef struct GListener {
58  gfxSem waitqueue; // Private: Semaphore for the listener to wait on.
59  uint16_t flags; // Private: Flags for operation
60  GEventCallbackFn callback; // Private: Call back Function
61  void *param; // Private: Parameter for the callback function.
62  GEvent event; // Public: The event object into which the event information is stored.
63  } GListener;
64 
65 // The Source Object
66 typedef struct GSource_t GSource, *GSourceHandle;
67 
68 // This structure is passed to a source to describe a contender listener for sending the current event.
69 typedef struct GSourceListener_t {
70  GListener *pListener; // The listener
71  GSource *pSource; // The source
72  uint32_t listenflags; // The flags the listener passed when the source was assigned to it.
73  uint32_t srcflags; // For the source's exclusive use. Initialised as 0 for a new listener source assignment.
74  } GSourceListener;
75 
76 /*===========================================================================*/
77 /* External declarations. */
78 /*===========================================================================*/
79 
80 #ifdef __cplusplus
81 extern "C" {
82 #endif
83 
84 /* How to listen for events (act as a Listener)...
85  1. Get handles for all the event sources you are interested in.
86  2. Initialise a listener
87  3. Attach sources to your listener.
88  - Sources can be attached or detached from a listener at any time.
89  - A source can be attached to more than one listener.
90  4. Loop on getting listener events
91  5. When finished detach all sources from the listener
92 
93  How to create events (act as a Source)...
94  1. Provide a funtion to the application that returns a GSourceHandle (which can be a pointer to whatever the source wants)
95  2. Whenever a possible event occurs call geventGetSourceListener() to get a pointer to a GSourceListener.
96  This will return NULL when there are no more listeners.
97  For each listener - check the flags to see if an event should be sent.
98  - use geventGetEventBuffer() to get the event buffer supplied by the listener
99  and then call geventSendEvent() to send the event.
100  - Note: geventGetEventBuffer() may return FALSE to indicate the listener is currently not listening and
101  therefore no event should be sent. This situation enables the source to (optionally) flag
102  to the listener on its next wait that there have been missed events.
103  - Note: The GSourceListener pointer (and the GEvent buffer) are only valid between
104  the geventGetSourceListener() call and either the geventSendEvent call or the next
105  geventGetSourceListener() call.
106  - Note: All listeners must be processed for this event before anything else is processed.
107 */
108 
109 /*---------- Listener Functions --------------------------------------------*/
110 
111 /**
112  * @brief Create a Listener
113  * @details If insufficient resources are available it will either assert or return NULL
114  * depending on the value of GEVENT_ASSERT_NO_RESOURCE.
115  *
116  * @param[in] pl A listener
117  */
118 void geventListenerInit(GListener *pl);
119 
120 /**
121  * @brief Attach a source to a listener
122  * @details Flags are interpreted by the source when generating events for each listener.
123  * If this source is already assigned to the listener it will update the flags.
124  * If insufficient resources are available it will either assert or return FALSE
125  * depending on the value of GEVENT_ASSERT_NO_RESOURCE.
126  *
127  * @param[in] pl The listener
128  * @param[in] gsh The source which has to be attached to the listener
129  * @param[in] flags The flags
130  *
131  * @return TRUE if succeeded, FALSE otherwise
132  */
133 bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, uint32_t flags);
134 
135 /**
136  * @brief Detach a source from a listener
137  * @details If gsh is NULL detach all sources from this listener and if there is still
138  * a thread waiting for events on this listener, it is sent the exit event.
139  *
140  * @param[in] pl The listener
141  * @param[in] gsh The source
142  */
143 void geventDetachSource(GListener *pl, GSourceHandle gsh);
144 
145 /**
146  * @brief Wait for an event on a listener from an assigned source.
147  * @details The type of the event should be checked (pevent->type) and then pevent should
148  * be typecast to the actual event type if it needs to be processed.
149  * TIME_INFINITE means no timeout - wait forever for an event.
150  * TIME_IMMEDIATE means return immediately
151  * @note The returned GEvent is released when this routine is called again
152  * or when optionally @p geventEventComplete() is called. Calling @p geventEventComplete()
153  * allows the GEvent object to be reused earlier which can reduce missed events. The GEvent
154  * object MUST NOT be used after this function is called (and is blocked waiting for the next
155  * event) or after geventEventComplete() is called.
156  * The one listener object should not be waited on using more than one thread simultanously
157  * because of the implicit geventEventComplete() that occurs when this function is called.
158  *
159  * @param[in] pl The listener
160  * @param[in] timeout The timeout in milliseconds
161  *
162  * @return NULL on timeout
163  */
164 GEvent *geventEventWait(GListener *pl, delaytime_t timeout);
165 
166 /**
167  * @brief Release the GEvent buffer associated with a listener.
168  * @details The GEvent returned by @p geventEventWait() is released.
169  * @note The GEvent pointer returned by @p geventEventWait() is released when @p geventEventWait()
170  * is called again or when this function is called. The GEvent
171  * object MUST NOT be used after this function is called.
172  *
173  * @param[in] pl The listener
174  */
175 void geventEventComplete(GListener *pl);
176 
177 /* @brief Register a callback for an event on a listener from an assigned source.
178  * @details The type of the event should be checked (pevent->type) and then pevent should be typecast to the
179  * actual event type if it needs to be processed.
180  *
181  * @params[in] pl The Listener
182  * @params[in] fn The function to call back
183  * @params[in] param A parameter to pass the callback function
184  *
185  * @note The GEvent buffer is valid only during the time of the callback. The callback MUST NOT save
186  * a pointer to the buffer for use outside the callback.
187  * @note An existing callback function is de-registered by passing a NULL for 'fn'. Any existing
188  * callback function is replaced. Any thread currently waiting using geventEventWait will be sent the exit event.
189  * @note Callbacks occur in a thread context but stack space must be kept to a minumum and
190  * the callback must process quickly as all other events are performed on a single thread.
191  * @note In the callback function you should never call ANY event functions using your own GListener handle
192  * as it WILL create a deadlock and lock the system up.
193  * @note Applications should not use this call - geventEventWait() is the preferred mechanism for an
194  * application. This call is provided for GUI objects that may not have their own thread.
195  */
196 void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param);
197 
198 /*---------- Source Functions --------------------------------------------*/
199 
200 /**
201  * @brief Called by a source with a possible event to get a listener record.
202  * @details @p lastlr should be NULL on the first call and thereafter the result of the previous call.
203  *
204  * @param[in] gsh The source handler
205  * @param[in] lastlr The source listener
206  *
207  * @return NULL when there are no more listeners for this source
208  */
209 GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr);
210 
211 /**
212  * @brief Get the event buffer from the GSourceListener.
213  * @details A NULL return allows the source to record (perhaps in glr->scrflags) that the listener
214  * has missed events. This can then be notified as part of the next event for the listener.
215  * The buffer can only be accessed untill the next call to @p geventGetSourceListener()
216  * or @p geventSendEvent()
217  *
218  * @param[in] psl The source listener
219  *
220  * @return NULL if the event buffer for this listener is currently in use.
221  */
222 GEvent *geventGetEventBuffer(GSourceListener *psl);
223 
224 /**
225  * @brief Called by a source to indicate the listener's event buffer has been filled.
226  * @details After calling this function the source must not reference in fields in the @p GSourceListener or the event buffer.
227  *
228  * @param[in] psl The source listener
229  */
230 void geventSendEvent(GSourceListener *psl);
231 
232 /**
233  * @brief Detach any listener that has this source attached
234  *
235  * @param[in] gsh The source handle
236  */
237 void geventDetachSourceListeners(GSourceHandle gsh);
238 
239 #ifdef __cplusplus
240 }
241 #endif
242 
243 #endif /* GFX_USE_GEVENT */
244 
245 #endif /* _GEVENT_H */
246 /** @} */
247 
bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, uint32_t flags)
Attach a source to a listener.
Definition: gevent.c:71
GEvent * geventGetEventBuffer(GSourceListener *psl)
Get the event buffer from the GSourceListener.
Definition: gevent.c:187
void geventListenerInit(GListener *pl)
Create a Listener.
Definition: gevent.c:64
#define GEVENT_MAXIMUM_SIZE
Defines the maximum size of an event status variable.
void geventEventComplete(GListener *pl)
Release the GEvent buffer associated with a listener.
Definition: gevent.c:146
A semaphore.
Definition: gos.h:105
GEvent * geventEventWait(GListener *pl, delaytime_t timeout)
Wait for an event on a listener from an assigned source.
Definition: gevent.c:118
void geventSendEvent(GSourceListener *psl)
Called by a source to indicate the listener's event buffer has been filled.
Definition: gevent.c:200
void geventDetachSource(GListener *pl, GSourceHandle gsh)
Detach a source from a listener.
Definition: gevent.c:108
void geventDetachSourceListeners(GSourceHandle gsh)
Detach any listener that has this source attached.
Definition: gevent.c:220
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
Definition: gevent.c:163