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_signal(gpointer handle);
27 static gboolean event_own (gpointer handle);
29 struct _WapiHandleOps _wapi_event_ops = {
31 event_signal, /* signal */
36 void _wapi_event_details (gpointer handle_info)
38 struct _WapiHandle_event *event = (struct _WapiHandle_event *)handle_info;
40 g_print ("manual: %s", event->manual?"TRUE":"FALSE");
43 static mono_once_t event_ops_once=MONO_ONCE_INIT;
45 static void event_ops_init (void)
47 _wapi_handle_register_capabilities (WAPI_HANDLE_EVENT,
48 WAPI_HANDLE_CAP_WAIT |
49 WAPI_HANDLE_CAP_SIGNAL);
52 static void event_signal(gpointer handle)
57 static gboolean event_own (gpointer handle)
59 struct _WapiHandle_event *event_handle;
62 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
63 (gpointer *)&event_handle);
65 g_warning ("%s: error looking up event handle %p", __func__,
71 g_message("%s: owning event handle %p", __func__, handle);
74 if(event_handle->manual==FALSE) {
75 g_assert (event_handle->set_count > 0);
77 if (--event_handle->set_count == 0) {
78 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
87 * @security: Ignored for now.
88 * @manual: Specifies whether the new event handle has manual or auto
90 * @initial: Specifies whether the new event handle is initially
92 * @name:Pointer to a string specifying the name of this name, or
93 * %NULL. Currently ignored.
95 * Creates a new event handle.
97 * An event handle is signalled with SetEvent(). If the new handle is
98 * a manual reset event handle, it remains signalled until it is reset
99 * with ResetEvent(). An auto reset event remains signalled until a
100 * single thread has waited for it, at which time the event handle is
101 * automatically reset to unsignalled.
103 * Return value: A new handle, or %NULL on error.
105 gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean manual,
106 gboolean initial, const gunichar2 *name G_GNUC_UNUSED)
108 struct _WapiHandle_event event_handle = {0};
112 mono_once (&event_ops_once, event_ops_init);
114 event_handle.manual = manual;
115 event_handle.set_count = 0;
117 if (initial == TRUE) {
118 if (manual == FALSE) {
119 event_handle.set_count = 1;
123 handle = _wapi_handle_new (WAPI_HANDLE_EVENT, &event_handle);
124 if (handle == _WAPI_HANDLE_INVALID) {
125 g_warning ("%s: error creating event handle", __func__);
126 SetLastError (ERROR_GEN_FAILURE);
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 if (initial == TRUE) {
136 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
140 g_message("%s: created new event handle %p", __func__, handle);
143 thr_ret = _wapi_handle_unlock_handle (handle);
144 g_assert (thr_ret == 0);
145 pthread_cleanup_pop (0);
152 * @handle: The event handle.
154 * Sets the event handle @handle to the signalled state, and then
155 * resets it to unsignalled after informing any waiting threads.
157 * If @handle is a manual reset event, all waiting threads that can be
158 * released immediately are released. @handle is then reset. If
159 * @handle is an auto reset event, one waiting thread is released even
160 * if multiple threads are waiting.
162 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
163 * ever returns %TRUE).
165 gboolean PulseEvent(gpointer handle)
167 struct _WapiHandle_event *event_handle;
171 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
172 (gpointer *)&event_handle);
174 g_warning ("%s: error looking up event handle %p", __func__,
179 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
181 thr_ret = _wapi_handle_lock_handle (handle);
182 g_assert (thr_ret == 0);
185 g_message("%s: Pulsing event handle %p", __func__, handle);
188 if(event_handle->manual==TRUE) {
189 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
191 event_handle->set_count++;
192 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
195 thr_ret = _wapi_handle_unlock_handle (handle);
196 g_assert (thr_ret == 0);
198 pthread_cleanup_pop (0);
200 if(event_handle->manual==TRUE) {
201 /* For a manual-reset event, we're about to try and
202 * get the handle lock again, so give other threads a
207 /* Reset the handle signal state */
208 /* I'm not sure whether or not we need a barrier here
209 * to make sure that all threads waiting on the event
210 * have proceeded. Currently we rely on broadcasting
214 g_message("%s: Obtained write lock on event handle %p",
218 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, handle);
219 thr_ret = _wapi_handle_lock_handle (handle);
220 g_assert (thr_ret == 0);
222 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
224 thr_ret = _wapi_handle_unlock_handle (handle);
225 g_assert (thr_ret == 0);
226 pthread_cleanup_pop (0);
234 * @handle: The event handle.
236 * Resets the event handle @handle to the unsignalled state.
238 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
239 * ever returns %TRUE).
241 gboolean ResetEvent(gpointer handle)
243 struct _WapiHandle_event *event_handle;
247 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
248 (gpointer *)&event_handle);
250 g_warning ("%s: error looking up event handle %p",
256 g_message("%s: Resetting event handle %p", __func__, handle);
259 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
261 thr_ret = _wapi_handle_lock_handle (handle);
262 g_assert (thr_ret == 0);
264 if(_wapi_handle_issignalled (handle)==FALSE) {
266 g_message("%s: No need to reset event handle %p", __func__,
271 g_message("%s: Obtained write lock on event handle %p",
275 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
278 event_handle->set_count = 0;
280 thr_ret = _wapi_handle_unlock_handle (handle);
281 g_assert (thr_ret == 0);
283 pthread_cleanup_pop (0);
290 * @handle: The event handle
292 * Sets the event handle @handle to the signalled state.
294 * If @handle is a manual reset event, it remains signalled until it
295 * is reset with ResetEvent(). An auto reset event remains signalled
296 * until a single thread has waited for it, at which time @handle is
297 * automatically reset to unsignalled.
299 * Return value: %TRUE on success, %FALSE otherwise. (Currently only
300 * ever returns %TRUE).
302 gboolean SetEvent(gpointer handle)
304 struct _WapiHandle_event *event_handle;
308 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
309 (gpointer *)&event_handle);
311 g_warning ("%s: error looking up event handle %p", __func__,
316 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
318 thr_ret = _wapi_handle_lock_handle (handle);
319 g_assert (thr_ret == 0);
322 g_message("%s: Setting event handle %p", __func__, handle);
325 if(event_handle->manual==TRUE) {
326 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
328 event_handle->set_count++;
329 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
332 thr_ret = _wapi_handle_unlock_handle (handle);
333 g_assert (thr_ret == 0);
335 pthread_cleanup_pop (0);