2002-04-30 Dick Porter <dick@ximian.com>
[mono.git] / mono / io-layer / events.c
index 829f8b8e2433d87420b065bfb8abff33d68b2c2a..4f522e3d452036d0070071fa4678da869be4cdfd 100644 (file)
@@ -3,42 +3,21 @@
 #include <pthread.h>
 #include <string.h>
 
-#include "mono/io-layer/wapi.h"
-#include "wapi-private.h"
-#include "wait-private.h"
-#include "handles-private.h"
-#include "misc-private.h"
+#include <mono/io-layer/wapi.h>
+#include <mono/io-layer/wapi-private.h>
+#include <mono/io-layer/wait-private.h>
+#include <mono/io-layer/handles-private.h>
+#include <mono/io-layer/misc-private.h>
 
-#include "mono-mutex.h"
+#include <mono/io-layer/mono-mutex.h>
 
-#undef DEBUG
-
-/* event_wait() uses the event-private condition to signal that the
- * event has been set
- *
- * Hold mutex before setting the event, and before the final test
- * Hold rwlock for reading while testing the event
- * Hold rwlock for writing before resetting the event
- */
-struct _WapiHandle_event
-{
-       WapiHandle handle;
-       mono_mutex_t mutex;
-       pthread_cond_t cond;
-       pthread_rwlock_t rwlock;
-       gboolean manual;
-};
+#include <mono/io-layer/event-private.h>
 
-/* event_wait_multiple() uses the global condition to signal that an
- * event has been set
- */
-static mono_mutex_t event_signal_mutex = MONO_MUTEX_INITIALIZER;
-static pthread_cond_t event_signal_cond = PTHREAD_COND_INITIALIZER;
+#undef DEBUG
 
-static void event_close(WapiHandle *handle);
-static gboolean event_wait(WapiHandle *handle, WapiHandle *signal, guint32 ms);
-static guint32 event_wait_multiple(gpointer data);
-static void event_signal(WapiHandle *handle);
+static void event_close(gpointer handle);
+static void event_signal(gpointer handle);
+static void event_own (gpointer handle);
 
 static struct _WapiHandleOps event_ops = {
        event_close,            /* close */
@@ -51,401 +30,64 @@ static struct _WapiHandleOps event_ops = {
        NULL,                   /* getfilesize */
        NULL,                   /* getfiletime */
        NULL,                   /* setfiletime */
-       event_wait,             /* wait */
-       event_wait_multiple,    /* wait_multiple */
        event_signal,           /* signal */
+       event_own,              /* own */
+       NULL,                   /* is_owned */
 };
 
-static void event_close(WapiHandle *handle)
-{
-       struct _WapiHandle_event *event_handle=(struct _WapiHandle_event *)handle;
-       
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": closing event handle %p",
-                 event_handle);
-#endif
+static pthread_once_t event_ops_once=PTHREAD_ONCE_INIT;
 
-       mono_mutex_destroy(&event_handle->mutex);
-       pthread_cond_destroy(&event_handle->cond);
-       pthread_rwlock_destroy(&event_handle->rwlock);
+static void event_ops_init (void)
+{
+       _wapi_handle_register_ops (WAPI_HANDLE_EVENT, &event_ops);
+       _wapi_handle_register_capabilities (WAPI_HANDLE_EVENT,
+                                           WAPI_HANDLE_CAP_WAIT |
+                                           WAPI_HANDLE_CAP_SIGNAL);
 }
 
-static gboolean event_wait(WapiHandle *handle, WapiHandle *signal, guint32 ms)
+static void event_close(gpointer handle)
 {
-       struct _WapiHandle_event *event_handle=(struct _WapiHandle_event *)handle;
-       struct timespec timeout;
-       int ret;
-
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": waiting on event handle %p for %d ms", handle, ms);
-#endif
-
-       mono_mutex_lock(&event_handle->mutex);
-
-       /* Signal this handle after we have obtained the event lock */
-       if(signal!=NULL) {
-               signal->ops->signal(signal);
-       }
-       
-       /* First check if the handle is already signalled */
-       if(handle->signalled==TRUE) {
-               /* If this is an auto-reset event, reset the state to
-                * unsignalled
-                */
-       
-#ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": event handle %p already signalled", handle);
-#endif
-
-               if(event_handle->manual==FALSE) {
-#ifdef DEBUG
-                       g_message(G_GNUC_PRETTY_FUNCTION
-                                 ": resetting auto event handle %p", handle);
-#endif
-                       handle->signalled=FALSE;
-               }
-               mono_mutex_unlock(&event_handle->mutex);
-               
-               return(TRUE);
-       }
-
-       /* We'll have to wait for it then */
-       if(ms!=INFINITE) {
-               _wapi_calc_timeout(&timeout, ms);
-       }
-       
-again:
-       /* Acquire a read lock so that the signal status can't be
-        * reset without us noticing. (PulseEvent and ResetEvent will
-        * gain a write lock before changing the status to
-        * unsignalled, which will block while one or more threads
-        * hold a read lock.)
-        */
-       pthread_rwlock_rdlock(&event_handle->rwlock);
-               
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": waiting for event handle %p to be signalled", handle);
-#endif
-
-       if(ms==INFINITE) {
-               ret=mono_cond_wait(&event_handle->cond,
-                                  &event_handle->mutex);
-       } else {
-               ret=mono_cond_timedwait(&event_handle->cond,
-                                       &event_handle->mutex, &timeout);
-       }
-
-       if(ret==0) {
-               /* Condition was signalled, so hopefully event is
-                * signalled now.  (It might not be if its an
-                * auto-reset event and someone else got in before
-                * us.)
-                */
-       
-#ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": event handle %p signalled",
-                         handle);
-#endif
-               if(handle->signalled==TRUE) {
-       
-#ifdef DEBUG
-                       g_message(G_GNUC_PRETTY_FUNCTION
-                                 ": event handle %p still signalled", handle);
-#endif
-                       /* If this is an auto-reset event, reset the
-                        * state to unsignalled
-                        */
-                       if(event_handle->manual==FALSE) {
-#ifdef DEBUG
-                               g_message(G_GNUC_PRETTY_FUNCTION
-                                         ": resetting auto event handle %p",
-                                         handle);
-#endif
-                               handle->signalled=FALSE;
-                       }
-                       pthread_rwlock_unlock(&event_handle->rwlock);
-                       mono_mutex_unlock(&event_handle->mutex);
-                       
-                       return(TRUE);
-               }
-       
-#ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": event handle %p no longer signalled", handle);
-#endif
-
-               /* Better luck next time */
-               
-               /* Drop the rwlock briefly so that another thread has
-                * a chance to reset the event
-                */
-               pthread_rwlock_unlock(&event_handle->rwlock);
-               goto again;
+       struct _WapiHandle_event *event_handle;
+       gboolean ok;
+       
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
+                               (gpointer *)&event_handle, NULL);
+       if(ok==FALSE) {
+               g_warning (G_GNUC_PRETTY_FUNCTION
+                          ": error looking up event handle %p", handle);
+               return;
        }
-
-       /* Timeout or other error */
        
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": wait on event handle %p error: %s", handle,
-                 strerror(ret));
+       g_message(G_GNUC_PRETTY_FUNCTION ": closing event handle %p", handle);
 #endif
-       
-       pthread_rwlock_unlock(&event_handle->rwlock);
-       mono_mutex_unlock(&event_handle->mutex);
-       
-       return(FALSE);
 }
 
-static gboolean event_count_signalled(WaitQueueItem *item, guint32 numhandles,
-                                     gboolean waitall, guint32 *retcount)
+static void event_signal(gpointer handle)
 {
-       guint32 count, i;
-       gboolean ret;
-       
-       /* Lock all the handles, with backoff */
-again:
-       for(i=0; i<numhandles; i++) {
-               struct _WapiHandle_event *event_handle;
-               
-               event_handle=g_ptr_array_index(
-                       item->handles[WAPI_HANDLE_EVENT], i);
-               
-               ret=mono_mutex_trylock(&event_handle->mutex);
-               if(ret!=0) {
-                       /* Bummer */
-                       while(i--) {
-                               event_handle=g_ptr_array_index(
-                                       item->handles[WAPI_HANDLE_EVENT], i);
-                               mono_mutex_unlock(&event_handle->mutex);
-                       }
-
-                       /* It's not possible for two threads calling
-                        * WaitForMultipleObjects to both be calling
-                        * this function simultaneously, because the
-                        * global event_signal_mutex is held.
-                        * Therefore any collision is with a single
-                        * lock from one of the functions that deal
-                        * with single event handles.  It's just about
-                        * theoretically possible for the other
-                        * threads to keep locking an event in a tight
-                        * loop but eventually we will get the lock.
-                        */
-                       sched_yield();
-                       
-                       goto again;
-               }
-       }
-       
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Locked all event handles");
-#endif
-       
-       count=_wapi_handle_count_signalled(item, WAPI_HANDLE_EVENT);
-       
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": %d event handles signalled",
-                 count);
-#endif
-       
-       if((waitall==TRUE && count==numhandles) ||
-          (waitall==FALSE && count>0)) {
-               /* done */
-               ret=TRUE;
-       } else {
-               ret=FALSE;
-       }
-       
-       for(i=0; i<numhandles; i++) {
-               struct _WapiHandle_event *event_handle;
-               
-               event_handle=g_ptr_array_index(
-                       item->handles[WAPI_HANDLE_EVENT], i);
-               
-               mono_mutex_unlock(&event_handle->mutex);
-       }
-       
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Returning %d", ret);
-#endif
-
-       *retcount=count;
-       return(ret);
+       ResetEvent(handle);
 }
 
-static guint32 event_wait_multiple(gpointer data)
+static void event_own (gpointer handle)
 {
-       WaitQueueItem *item=(WaitQueueItem *)data;
-       struct timespec timeout;
-       guint32 iterations;
-       guint32 numhandles, count, i;
-       gboolean done;
-       int ret;
-
-       numhandles=item->handles[WAPI_HANDLE_EVENT]->len;
-       
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": waiting on %d event handles for %d ms", numhandles,
-                 item->timeout);
-#endif
-
-       /* First, check if any of the handles are already
-        * signalled. If waitall is specified we only return if all
-        * handles have been signalled.
-        */
-       done=event_count_signalled(item, numhandles, item->waitall, &count);
-       
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": Preliminary check found %d handles signalled", count);
-#endif
-
-       if(done==TRUE) {
-               item->waited[WAPI_HANDLE_EVENT]=TRUE;
-               item->waitcount[WAPI_HANDLE_EVENT]=count;
-               
-               return(count);
+       struct _WapiHandle_event *event_handle;
+       gboolean ok;
+       
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
+                               (gpointer *)&event_handle, NULL);
+       if(ok==FALSE) {
+               g_warning (G_GNUC_PRETTY_FUNCTION
+                          ": error looking up event handle %p", handle);
+               return;
        }
        
-       /* We'll have to wait then */
-       
-       mono_mutex_lock(&event_signal_mutex);
-       
-       iterations=0;
-       do {
-               iterations++;
-               
-#ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": Wait iteration %d",
-                         iterations);
-#endif
-
-               /* If the timeout isnt INFINITE but greater than 1s,
-                * split the timeout into 1s chunks.
-                *
-                * This is so that ResetEvent() wont block forever if
-                * another thread is waiting on multiple events, with
-                * some already signalled, and ResetEvent() wants to
-                * reset one of the signalled ones.  (1s is a bit of a
-                * long wait too, this might need to be tuned.)
-                */
-
-               if((item->timeout!=INFINITE) &&
-                  (item->timeout < (iterations*1000))) {
-                       _wapi_calc_timeout(
-                               &timeout, item->timeout-((iterations-1)*1000));
-               } else {
-                       _wapi_calc_timeout(&timeout, 1000);
-               }
-               
-               /* Acquire a read lock on all handles so that the
-                * signal status can't be reset without us
-                * noticing. (PulseEvent and ResetEvent will gain a
-                * write lock before changing the status to
-                * unsignalled, which will block while one or more
-                * threads hold a read lock.)
-                */
-               for(i=0; i<numhandles; i++) {
-                       struct _WapiHandle_event *event_handle;
-                       
-                       event_handle=g_ptr_array_index(
-                               item->handles[WAPI_HANDLE_EVENT], i);
-                       
-                       pthread_rwlock_rdlock(&event_handle->rwlock);
-               }
-               
-               ret=mono_cond_timedwait(&event_signal_cond,
-                                          &event_signal_mutex, &timeout);
-
-               if(ret==0) {
-                       /* Condition was signalled, so hopefully an
-                        * event is signalled now.  (It might not be
-                        * if it was an auto-reset event and someone
-                        * else got in before us.)
-                        */
-                       done=event_count_signalled(item, numhandles,
-                                                  item->waitall, &count);
-       
 #ifdef DEBUG
-                       g_message(G_GNUC_PRETTY_FUNCTION
-                                 ": signal check found %d handles signalled",
-                                 count);
+       g_message(G_GNUC_PRETTY_FUNCTION ": owning event handle %p", handle);
 #endif
-                       
-                       if(done==TRUE) {
-#ifdef DEBUG
-                               g_message(G_GNUC_PRETTY_FUNCTION
-                                         ": Returning wait success");
-#endif
-
-                               for(i=0; i<numhandles; i++) {
-                                       struct _WapiHandle_event *event_handle;
-                               
-                                       event_handle=g_ptr_array_index(item->handles[WAPI_HANDLE_EVENT], i);
-                       
-                                       pthread_rwlock_unlock(&event_handle->rwlock);
-                               }
-
-                               item->waited[WAPI_HANDLE_EVENT]=TRUE;
-                               item->waitcount[WAPI_HANDLE_EVENT]=count;
-                               
-                               return(count);
-                       }
-               } else {
-#ifdef DEBUG
-                       g_message(G_GNUC_PRETTY_FUNCTION ": Wait error %s",
-                                 strerror(ret));
-#endif
-               }
 
-#ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": Still waiting for more event handles");
-#endif
-               /* Drop the rwlocks briefly so that another thread has
-                * a chance to reset any of the events
-                */
-               for(i=0; i<numhandles; i++) {
-                       struct _WapiHandle_event *event_handle;
-                               
-                       event_handle=g_ptr_array_index(
-                               item->handles[WAPI_HANDLE_EVENT], i);
-                       
-                       pthread_rwlock_unlock(&event_handle->rwlock);
-               }
-       } while((item->timeout==INFINITE) ||
-               (item->timeout > (iterations * 1000)));
-
-       /* Timeout or other error */
-       
-       for(i=0; i<numhandles; i++) {
-               struct _WapiHandle_event *event_handle;
-               
-               event_handle=g_ptr_array_index(
-                       item->handles[WAPI_HANDLE_EVENT], i);
-               
-               pthread_rwlock_unlock(&event_handle->rwlock);
+       if(event_handle->manual==FALSE) {
+               _wapi_handle_set_signal_state (handle, FALSE, FALSE);
        }
-
-       mono_mutex_unlock(&event_signal_mutex);
-
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Returning wait failed");
-#endif
-       
-       item->waited[WAPI_HANDLE_EVENT]=TRUE;
-       item->waitcount[WAPI_HANDLE_MUTEX]=0;
-       
-       return(0);
-}
-
-static void event_signal(WapiHandle *handle)
-{
-       ResetEvent(handle);
 }
 
 /**
@@ -468,23 +110,37 @@ static void event_signal(WapiHandle *handle)
  *
  * Return value: A new handle, or %NULL on error.
  */
-WapiHandle *CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean manual,
-                       gboolean initial, const guchar *name G_GNUC_UNUSED)
+gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean manual,
+                    gboolean initial, const guchar *name G_GNUC_UNUSED)
 {
        struct _WapiHandle_event *event_handle;
-       WapiHandle *handle;
+       gpointer handle;
+       gboolean ok;
        
-       event_handle=(struct _WapiHandle_event *)g_new0(struct _WapiHandle_event, 1);
-       handle=(WapiHandle *)event_handle;
-       _WAPI_HANDLE_INIT(handle, WAPI_HANDLE_EVENT, event_ops);
+       pthread_once (&event_ops_once, event_ops_init);
+
+       handle=_wapi_handle_new (WAPI_HANDLE_EVENT);
+       if(handle==_WAPI_HANDLE_INVALID) {
+               g_warning (G_GNUC_PRETTY_FUNCTION
+                          ": error creating event handle");
+               return(NULL);
+       }
+       
+       _wapi_handle_lock_handle (handle);
+       
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
+                               (gpointer *)&event_handle, NULL);
+       if(ok==FALSE) {
+               g_warning (G_GNUC_PRETTY_FUNCTION
+                          ": error looking up event handle %p", handle);
+               _wapi_handle_unlock_handle (handle);
+               return(NULL);
+       }
        
-       mono_mutex_init(&event_handle->mutex, NULL);
-       pthread_cond_init(&event_handle->cond, NULL);
-       pthread_rwlock_init(&event_handle->rwlock, NULL);
        event_handle->manual=manual;
 
        if(initial==TRUE) {
-               handle->signalled=TRUE;
+               _wapi_handle_set_signal_state (handle, TRUE, FALSE);
        }
        
 #ifdef DEBUG
@@ -492,6 +148,8 @@ WapiHandle *CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean
                  handle);
 #endif
 
+       _wapi_handle_unlock_handle (handle);
+       
        return(handle);
 }
 
@@ -510,56 +168,55 @@ WapiHandle *CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean
  * Return value: %TRUE on success, %FALSE otherwise.  (Currently only
  * ever returns %TRUE).
  */
-gboolean PulseEvent(WapiHandle *handle)
+gboolean PulseEvent(gpointer handle)
 {
-       struct _WapiHandle_event *event_handle=(struct _WapiHandle_event *)handle;
+       struct _WapiHandle_event *event_handle;
+       gboolean ok;
+       
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
+                               (gpointer *)&event_handle, NULL);
+       if(ok==FALSE) {
+               g_warning (G_GNUC_PRETTY_FUNCTION
+                          ": error looking up event handle %p", handle);
+               return(FALSE);
+       }
        
-       mono_mutex_lock(&event_handle->mutex);
+       _wapi_handle_lock_handle (handle);
 
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": Pulsing event handle %p", handle);
 #endif
 
-       handle->signalled=TRUE;
-       
-       /* Tell everyone blocking on WaitForSingleObject */
        if(event_handle->manual==TRUE) {
-               pthread_cond_broadcast(&event_handle->cond);
+               _wapi_handle_set_signal_state (handle, TRUE, TRUE);
        } else {
-               pthread_cond_signal(&event_handle->cond);
+               _wapi_handle_set_signal_state (handle, TRUE, FALSE);
        }
-       mono_mutex_unlock(&event_handle->mutex);
-
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": Informed single waits for event handle %p", handle);
-#endif
-       
-       /* Tell everyone blocking on WaitForMultipleObjects */
-       mono_mutex_lock(&event_signal_mutex);
-       pthread_cond_broadcast(&event_signal_cond);
-       mono_mutex_unlock(&event_signal_mutex);
 
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": Informed multiple waits for event handles");
-#endif
+       _wapi_handle_unlock_handle (handle);
        
-       /* Reset the handle signal state */
-
-       /* This rwlock blocks until no other thread holds a read lock.
-        * This ensures that we can't reset the event until every
-        * waiting thread has had a chance to examine it
-        */
-       pthread_rwlock_wrlock(&event_handle->rwlock);
+       if(event_handle->manual==TRUE) {
+               /* For a manual-reset event, we're about to try and
+                * get the handle lock again, so give other threads a
+                * chance
+                */
+               sched_yield ();
 
+               /* Reset the handle signal state */
+               /* I'm not sure whether or not we need a barrier here
+                * to make sure that all threads waiting on the event
+                * have proceeded.  Currently we rely on broadcasting
+                * a condition.
+                */
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": Obtained write lock on event handle %p", handle);
+               g_message(G_GNUC_PRETTY_FUNCTION
+                         ": Obtained write lock on event handle %p", handle);
 #endif
 
-       handle->signalled=FALSE;
-       pthread_rwlock_unlock(&event_handle->rwlock);
+               _wapi_handle_lock_handle (handle);
+               _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+               _wapi_handle_unlock_handle (handle);
+       }
 
        return(TRUE);
 }
@@ -573,42 +230,44 @@ gboolean PulseEvent(WapiHandle *handle)
  * Return value: %TRUE on success, %FALSE otherwise.  (Currently only
  * ever returns %TRUE).
  */
-gboolean ResetEvent(WapiHandle *handle)
+gboolean ResetEvent(gpointer handle)
 {
-       struct _WapiHandle_event *event_handle=(struct _WapiHandle_event *)handle;
+       struct _WapiHandle_event *event_handle;
+       gboolean ok;
+       
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
+                               (gpointer *)&event_handle, NULL);
+       if(ok==FALSE) {
+               g_warning (G_GNUC_PRETTY_FUNCTION
+                          ": error looking up event handle %p", handle);
+               return(FALSE);
+       }
 
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": Resetting event handle %p",
                  handle);
 #endif
 
-       /* Test for the current state, because another thread might be
-        * waiting forever on an unsignalled event with the read lock
-        * held.  Theres no point going for the write lock if we dont
-        * need it.
-        */
-       mono_mutex_lock(&event_handle->mutex);
-       if(handle->signalled==FALSE) {
+       _wapi_handle_lock_handle (handle);
+       if(_wapi_handle_issignalled (handle)==FALSE) {
 
 #ifdef DEBUG
                g_message(G_GNUC_PRETTY_FUNCTION
                          ": No need to reset event handle %p", handle);
 #endif
 
-               mono_mutex_unlock(&event_handle->mutex);
+               _wapi_handle_unlock_handle (handle);
                return(TRUE);
        }
-       mono_mutex_unlock(&event_handle->mutex);
        
-       pthread_rwlock_wrlock(&event_handle->rwlock);
-
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION
                  ": Obtained write lock on event handle %p", handle);
 #endif
 
-       handle->signalled=FALSE;
-       pthread_rwlock_unlock(&event_handle->rwlock);
+       _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+
+       _wapi_handle_unlock_handle (handle);
        
        return(TRUE);
 }
@@ -627,41 +286,33 @@ gboolean ResetEvent(WapiHandle *handle)
  * Return value: %TRUE on success, %FALSE otherwise.  (Currently only
  * ever returns %TRUE).
  */
-gboolean SetEvent(WapiHandle *handle)
+gboolean SetEvent(gpointer handle)
 {
-       struct _WapiHandle_event *event_handle=(struct _WapiHandle_event *)handle;
+       struct _WapiHandle_event *event_handle;
+       gboolean ok;
+       
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
+                               (gpointer *)&event_handle, NULL);
+       if(ok==FALSE) {
+               g_warning (G_GNUC_PRETTY_FUNCTION
+                          ": error looking up event handle %p", handle);
+               return(FALSE);
+       }
        
-       mono_mutex_lock(&event_handle->mutex);
+       _wapi_handle_lock_handle (handle);
 
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": Setting event handle %p", handle);
 #endif
 
-       handle->signalled=TRUE;
-       
-       /* Tell everyone blocking on WaitForSingleObject */
        if(event_handle->manual==TRUE) {
-               pthread_cond_broadcast(&event_handle->cond);
+               _wapi_handle_set_signal_state (handle, TRUE, TRUE);
        } else {
-               pthread_cond_signal(&event_handle->cond);
+               _wapi_handle_set_signal_state (handle, TRUE, FALSE);
        }
-       mono_mutex_unlock(&event_handle->mutex);
 
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": Informed single waits for event handle %p", handle);
-#endif
-       
-       /* Tell everyone blocking on WaitForMultipleObjects */
-       mono_mutex_lock(&event_signal_mutex);
-       pthread_cond_broadcast(&event_signal_cond);
-       mono_mutex_unlock(&event_signal_mutex);
+       _wapi_handle_unlock_handle (handle);
 
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": Informed multiple waits for event handles");
-#endif
-       
        return(TRUE);
 }