2 * events.c: Event handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
15 #include <mono/io-layer/wapi.h>
16 #include <mono/io-layer/wapi-private.h>
17 #include <mono/io-layer/handles-private.h>
18 #include <mono/io-layer/misc-private.h>
20 #include <mono/io-layer/mono-mutex.h>
22 #include <mono/io-layer/event-private.h>
26 static void event_close_shared (gpointer handle);
27 static void event_signal(gpointer handle);
28 static void event_own (gpointer handle);
30 struct _WapiHandleOps _wapi_event_ops = {
31 event_close_shared, /* close_shared */
32 NULL, /* close_private */
33 event_signal, /* signal */
38 static mono_once_t event_ops_once=MONO_ONCE_INIT;
40 static void event_ops_init (void)
42 _wapi_handle_register_capabilities (WAPI_HANDLE_EVENT,
43 WAPI_HANDLE_CAP_WAIT |
44 WAPI_HANDLE_CAP_SIGNAL);
47 static void event_close_shared(gpointer handle)
49 struct _WapiHandle_event *event_handle;
52 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
53 (gpointer *)&event_handle, NULL);
55 g_warning (G_GNUC_PRETTY_FUNCTION
56 ": error looking up event handle %p", handle);
61 g_message(G_GNUC_PRETTY_FUNCTION ": closing event handle %p", handle);
65 static void event_signal(gpointer handle)
70 static void event_own (gpointer handle)
72 struct _WapiHandle_event *event_handle;
75 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
76 (gpointer *)&event_handle, NULL);
78 g_warning (G_GNUC_PRETTY_FUNCTION
79 ": error looking up event handle %p", handle);
84 g_message(G_GNUC_PRETTY_FUNCTION ": owning event handle %p", handle);
87 if(event_handle->manual==FALSE) {
88 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
94 * @security: Ignored for now.
95 * @manual: Specifies whether the new event handle has manual or auto
97 * @initial: Specifies whether the new event handle is initially
99 * @name:Pointer to a string specifying the name of this name, or
100 * %NULL. Currently ignored.
102 * Creates a new event handle.
104 * An event handle is signalled with SetEvent(). If the new handle is
105 * a manual reset event handle, it remains signalled until it is reset
106 * with ResetEvent(). An auto reset event remains signalled until a
107 * single thread has waited for it, at which time the event handle is
108 * automatically reset to unsignalled.
110 * Return value: A new handle, or %NULL on error.
112 gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean manual,
113 gboolean initial, const gunichar2 *name G_GNUC_UNUSED)
115 struct _WapiHandle_event *event_handle;
121 mono_once (&event_ops_once, event_ops_init);
123 handle=_wapi_handle_new (WAPI_HANDLE_EVENT);
124 if(handle==_WAPI_HANDLE_INVALID) {
125 g_warning (G_GNUC_PRETTY_FUNCTION
126 ": error creating event handle");
130 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
132 thr_ret = _wapi_handle_lock_handle (handle);
133 g_assert (thr_ret == 0);
135 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
136 (gpointer *)&event_handle, NULL);
138 g_warning (G_GNUC_PRETTY_FUNCTION
139 ": error looking up event handle %p", handle);
144 event_handle->manual=manual;
147 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
151 g_message(G_GNUC_PRETTY_FUNCTION ": created new event handle %p",
156 thr_ret = _wapi_handle_unlock_handle (handle);
157 g_assert (thr_ret == 0);
159 pthread_cleanup_pop (0);
166 * @handle: The event handle.
168 * Sets the event handle @handle to the signalled state, and then
169 * resets it to unsignalled after informing any waiting threads.
171 * If @handle is a manual reset event, all waiting threads that can be
172 * released immediately are released. @handle is then reset. If
173 * @handle is an auto reset event, one waiting thread is released even
174 * if multiple threads are waiting.
176 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
177 * ever returns %TRUE).
179 gboolean PulseEvent(gpointer handle)
181 struct _WapiHandle_event *event_handle;
185 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
186 (gpointer *)&event_handle, NULL);
188 g_warning (G_GNUC_PRETTY_FUNCTION
189 ": error looking up event handle %p", handle);
193 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
195 thr_ret = _wapi_handle_lock_handle (handle);
196 g_assert (thr_ret == 0);
199 g_message(G_GNUC_PRETTY_FUNCTION ": Pulsing event handle %p", handle);
202 if(event_handle->manual==TRUE) {
203 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
205 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
208 thr_ret = _wapi_handle_unlock_handle (handle);
209 g_assert (thr_ret == 0);
211 pthread_cleanup_pop (0);
213 if(event_handle->manual==TRUE) {
214 /* For a manual-reset event, we're about to try and
215 * get the handle lock again, so give other threads a
220 /* Reset the handle signal state */
221 /* I'm not sure whether or not we need a barrier here
222 * to make sure that all threads waiting on the event
223 * have proceeded. Currently we rely on broadcasting
227 g_message(G_GNUC_PRETTY_FUNCTION
228 ": Obtained write lock on event handle %p", handle);
231 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, handle);
232 thr_ret = _wapi_handle_lock_handle (handle);
233 g_assert (thr_ret == 0);
235 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
237 thr_ret = _wapi_handle_unlock_handle (handle);
238 g_assert (thr_ret == 0);
239 pthread_cleanup_pop (0);
247 * @handle: The event handle.
249 * Resets the event handle @handle to the unsignalled state.
251 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
252 * ever returns %TRUE).
254 gboolean ResetEvent(gpointer handle)
256 struct _WapiHandle_event *event_handle;
260 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
261 (gpointer *)&event_handle, NULL);
263 g_warning (G_GNUC_PRETTY_FUNCTION
264 ": error looking up event handle %p", handle);
269 g_message(G_GNUC_PRETTY_FUNCTION ": Resetting event handle %p",
273 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
275 thr_ret = _wapi_handle_lock_handle (handle);
276 g_assert (thr_ret == 0);
278 if(_wapi_handle_issignalled (handle)==FALSE) {
280 g_message(G_GNUC_PRETTY_FUNCTION
281 ": No need to reset event handle %p", handle);
285 g_message(G_GNUC_PRETTY_FUNCTION
286 ": Obtained write lock on event handle %p", handle);
289 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
292 thr_ret = _wapi_handle_unlock_handle (handle);
293 g_assert (thr_ret == 0);
295 pthread_cleanup_pop (0);
302 * @handle: The event handle
304 * Sets the event handle @handle to the signalled state.
306 * If @handle is a manual reset event, it remains signalled until it
307 * is reset with ResetEvent(). An auto reset event remains signalled
308 * until a single thread has waited for it, at which time @handle is
309 * automatically reset to unsignalled.
311 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
312 * ever returns %TRUE).
314 gboolean SetEvent(gpointer handle)
316 struct _WapiHandle_event *event_handle;
320 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
321 (gpointer *)&event_handle, NULL);
323 g_warning (G_GNUC_PRETTY_FUNCTION
324 ": error looking up event handle %p", handle);
328 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
330 thr_ret = _wapi_handle_lock_handle (handle);
331 g_assert (thr_ret == 0);
334 g_message(G_GNUC_PRETTY_FUNCTION ": Setting event handle %p", handle);
337 if(event_handle->manual==TRUE) {
338 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
340 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
343 thr_ret = _wapi_handle_unlock_handle (handle);
344 g_assert (thr_ret == 0);
346 pthread_cleanup_pop (0);