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 g_assert (event_handle
->set_count
> 0);
90 if (--event_handle
->set_count
== 0) {
91 _wapi_handle_set_signal_state (handle
, FALSE
, FALSE
);
98 * @security: Ignored for now.
99 * @manual: Specifies whether the new event handle has manual or auto
101 * @initial: Specifies whether the new event handle is initially
103 * @name:Pointer to a string specifying the name of this name, or
104 * %NULL. Currently ignored.
106 * Creates a new event handle.
108 * An event handle is signalled with SetEvent(). If the new handle is
109 * a manual reset event handle, it remains signalled until it is reset
110 * with ResetEvent(). An auto reset event remains signalled until a
111 * single thread has waited for it, at which time the event handle is
112 * automatically reset to unsignalled.
114 * Return value: A new handle, or %NULL on error.
116 gpointer
CreateEvent(WapiSecurityAttributes
*security G_GNUC_UNUSED
, gboolean manual
,
117 gboolean initial
, const gunichar2
*name G_GNUC_UNUSED
)
119 struct _WapiHandle_event
*event_handle
;
125 mono_once (&event_ops_once
, event_ops_init
);
127 handle
=_wapi_handle_new (WAPI_HANDLE_EVENT
);
128 if(handle
==_WAPI_HANDLE_INVALID
) {
129 g_warning (G_GNUC_PRETTY_FUNCTION
130 ": error creating event handle");
134 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle
,
136 thr_ret
= _wapi_handle_lock_handle (handle
);
137 g_assert (thr_ret
== 0);
139 ok
=_wapi_lookup_handle (handle
, WAPI_HANDLE_EVENT
,
140 (gpointer
*)&event_handle
, NULL
);
142 g_warning (G_GNUC_PRETTY_FUNCTION
143 ": error looking up event handle %p", handle
);
148 event_handle
->manual
=manual
;
149 event_handle
->set_count
= 0;
152 if (manual
== FALSE
) {
153 event_handle
->set_count
= 1;
156 _wapi_handle_set_signal_state (handle
, TRUE
, FALSE
);
160 g_message(G_GNUC_PRETTY_FUNCTION
": created new event handle %p",
165 thr_ret
= _wapi_handle_unlock_handle (handle
);
166 g_assert (thr_ret
== 0);
168 pthread_cleanup_pop (0);
175 * @handle: The event handle.
177 * Sets the event handle @handle to the signalled state, and then
178 * resets it to unsignalled after informing any waiting threads.
180 * If @handle is a manual reset event, all waiting threads that can be
181 * released immediately are released. @handle is then reset. If
182 * @handle is an auto reset event, one waiting thread is released even
183 * if multiple threads are waiting.
185 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
186 * ever returns %TRUE).
188 gboolean
PulseEvent(gpointer handle
)
190 struct _WapiHandle_event
*event_handle
;
194 ok
=_wapi_lookup_handle (handle
, WAPI_HANDLE_EVENT
,
195 (gpointer
*)&event_handle
, NULL
);
197 g_warning (G_GNUC_PRETTY_FUNCTION
198 ": error looking up event handle %p", handle
);
202 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle
,
204 thr_ret
= _wapi_handle_lock_handle (handle
);
205 g_assert (thr_ret
== 0);
208 g_message(G_GNUC_PRETTY_FUNCTION
": Pulsing event handle %p", handle
);
211 if(event_handle
->manual
==TRUE
) {
212 _wapi_handle_set_signal_state (handle
, TRUE
, TRUE
);
214 event_handle
->set_count
++;
215 _wapi_handle_set_signal_state (handle
, TRUE
, FALSE
);
218 thr_ret
= _wapi_handle_unlock_handle (handle
);
219 g_assert (thr_ret
== 0);
221 pthread_cleanup_pop (0);
223 if(event_handle
->manual
==TRUE
) {
224 /* For a manual-reset event, we're about to try and
225 * get the handle lock again, so give other threads a
230 /* Reset the handle signal state */
231 /* I'm not sure whether or not we need a barrier here
232 * to make sure that all threads waiting on the event
233 * have proceeded. Currently we rely on broadcasting
237 g_message(G_GNUC_PRETTY_FUNCTION
238 ": Obtained write lock on event handle %p", handle
);
241 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle
, handle
);
242 thr_ret
= _wapi_handle_lock_handle (handle
);
243 g_assert (thr_ret
== 0);
245 _wapi_handle_set_signal_state (handle
, FALSE
, FALSE
);
247 thr_ret
= _wapi_handle_unlock_handle (handle
);
248 g_assert (thr_ret
== 0);
249 pthread_cleanup_pop (0);
257 * @handle: The event handle.
259 * Resets the event handle @handle to the unsignalled state.
261 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
262 * ever returns %TRUE).
264 gboolean
ResetEvent(gpointer handle
)
266 struct _WapiHandle_event
*event_handle
;
270 ok
=_wapi_lookup_handle (handle
, WAPI_HANDLE_EVENT
,
271 (gpointer
*)&event_handle
, NULL
);
273 g_warning (G_GNUC_PRETTY_FUNCTION
274 ": error looking up event handle %p", handle
);
279 g_message(G_GNUC_PRETTY_FUNCTION
": Resetting event handle %p",
283 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle
,
285 thr_ret
= _wapi_handle_lock_handle (handle
);
286 g_assert (thr_ret
== 0);
288 if(_wapi_handle_issignalled (handle
)==FALSE
) {
290 g_message(G_GNUC_PRETTY_FUNCTION
291 ": No need to reset event handle %p", handle
);
295 g_message(G_GNUC_PRETTY_FUNCTION
296 ": Obtained write lock on event handle %p", handle
);
299 _wapi_handle_set_signal_state (handle
, FALSE
, FALSE
);
302 event_handle
->set_count
= 0;
304 thr_ret
= _wapi_handle_unlock_handle (handle
);
305 g_assert (thr_ret
== 0);
307 pthread_cleanup_pop (0);
314 * @handle: The event handle
316 * Sets the event handle @handle to the signalled state.
318 * If @handle is a manual reset event, it remains signalled until it
319 * is reset with ResetEvent(). An auto reset event remains signalled
320 * until a single thread has waited for it, at which time @handle is
321 * automatically reset to unsignalled.
323 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
324 * ever returns %TRUE).
326 gboolean
SetEvent(gpointer handle
)
328 struct _WapiHandle_event
*event_handle
;
332 ok
=_wapi_lookup_handle (handle
, WAPI_HANDLE_EVENT
,
333 (gpointer
*)&event_handle
, NULL
);
335 g_warning (G_GNUC_PRETTY_FUNCTION
336 ": error looking up event handle %p", handle
);
340 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle
,
342 thr_ret
= _wapi_handle_lock_handle (handle
);
343 g_assert (thr_ret
== 0);
346 g_message(G_GNUC_PRETTY_FUNCTION
": Setting event handle %p", handle
);
349 if(event_handle
->manual
==TRUE
) {
350 _wapi_handle_set_signal_state (handle
, TRUE
, TRUE
);
352 event_handle
->set_count
++;
353 _wapi_handle_set_signal_state (handle
, TRUE
, FALSE
);
356 thr_ret
= _wapi_handle_unlock_handle (handle
);
357 g_assert (thr_ret
== 0);
359 pthread_cleanup_pop (0);