Code opschonen, toevoegen documentatie
[projects/chimara/chimara.git] / src / event.c
index 0334e3925129618a3b21d1a747a04a44c656d119..76f82409ad5bcddf4201fa2e17b60b23c20c7796 100644 (file)
@@ -1,10 +1,13 @@
 #include "event.h"
+#include <string.h>
 
 static GQueue *event_queue = NULL;
 static GMutex *event_lock = NULL;
 static GCond *event_queue_not_empty = NULL;
 static GCond *event_queue_not_full = NULL;
 
+/* Internal function: initialize the event_queue, locking and signalling 
+objects. */
 void
 events_init()
 {
@@ -14,22 +17,20 @@ events_init()
        event_queue_not_full = g_cond_new();
 }
 
-static void
-event_free(gpointer data, gpointer user_data)
-{
-       g_free(data);
-}
-
+/* Internal function: free the event queue and all the objects allocated in
+events_init(). */
 void
 events_free()
 {
-       g_queue_foreach(event_queue, event_free, NULL);
+       g_queue_foreach(event_queue, (GFunc)g_free, NULL);
        g_queue_free(event_queue);
        g_mutex_free(event_lock);
        g_cond_free(event_queue_not_empty);
        g_cond_free(event_queue_not_full);
 }
 
+/* Internal function: push an event onto the event queue. If the event queue is
+full, wait for max three seconds and then drop the event. */
 void
 event_throw(glui32 type, winid_t win, glui32 val1, glui32 val2)
 {
@@ -37,22 +38,22 @@ event_throw(glui32 type, winid_t win, glui32 val1, glui32 val2)
        g_get_current_time(&timeout);
        g_time_val_add(&timeout, 3000000); /* 3 Seconds */
 
-       /* Wait for room in the event queue */
        g_mutex_lock(event_lock);
-       if( g_queue_get_length(event_queue) >= EVENT_QUEUE_MAX_LENGTH ) {
-               if( !g_cond_timed_wait(event_queue_not_full, event_lock, &timeout) ) {
-                       /* Drop the event */
+
+       /* Wait for room in the event queue */
+       if( g_queue_get_length(event_queue) >= EVENT_QUEUE_MAX_LENGTH )
+               if( !g_cond_timed_wait(event_queue_not_full, event_lock, &timeout) ) 
+               {
+                       /* Drop the event after 3 seconds */
                        g_mutex_unlock(event_lock);
                        return;
                }
-       }
 
        event_t *event = g_new0(event_t, 1);
        event->type = type;
        event->win = win;
        event->val1 = val1;
        event->val2 = val2;
-
        g_queue_push_head(event_queue, event);
 
        /* Signal that there is an event */
@@ -61,28 +62,38 @@ event_throw(glui32 type, winid_t win, glui32 val1, glui32 val2)
        g_mutex_unlock(event_lock);
 }
 
+/**
+ * glk_select:
+ * @event: Pointer to an #event_t.
+ *
+ * Causes the program to wait for an event, and then store it in the structure
+ * pointed to by @event. Unlike most Glk functions that take pointers, the
+ * argument of glk_select() may not be %NULL.
+ *
+ * Most of the time, you only get the events that you request. However, there
+ * are some events which can arrive at any time. This is why you must always
+ * call glk_select() in a loop, and continue the loop until you get the event
+ * you really want.
+ */
 void
 glk_select(event_t *event)
 {
-       event_t *retrieved_event;
-
        g_return_if_fail(event != NULL);
 
        g_mutex_lock(event_lock);
 
        /* Wait for an event */
-       if( g_queue_is_empty(event_queue) ) {
+       if( g_queue_is_empty(event_queue) )
                g_cond_wait(event_queue_not_empty, event_lock);
-       }
-
-       retrieved_event = g_queue_pop_tail(event_queue);
-       g_return_if_fail(retrieved_event != NULL);
-
-       event->type = retrieved_event->type;
-       event->win = retrieved_event->win;
-       event->val1 = retrieved_event->val1;
-       event->val2 = retrieved_event->val2;
 
+       event_t *retrieved_event = g_queue_pop_tail(event_queue);
+       if(retrieved_event == NULL)
+       {
+               g_mutex_unlock(event_lock);
+               g_warning("%s: Retrieved NULL event from non-empty event queue", __func__);
+               return;
+       }
+       memcpy(event, retrieved_event, sizeof(event_t));
        g_free(retrieved_event);
 
        /* Signal that the event queue is no longer full */
@@ -90,7 +101,7 @@ glk_select(event_t *event)
 
        g_mutex_unlock(event_lock);
 
-       /* Implementation defined events */
+       /* Implementation-defined events */
        switch(event->type) {
                case EVENT_TYPE_QUIT:
                        g_thread_exit(NULL);