check_for_abort(void)
{
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
- g_mutex_lock(glk_data->abort_lock);
+ g_mutex_lock(&glk_data->abort_lock);
if(glk_data->abort_signalled)
{
- g_mutex_unlock(glk_data->abort_lock);
+ g_mutex_unlock(&glk_data->abort_lock);
abort_glk();
}
- g_mutex_unlock(glk_data->abort_lock);
+ g_mutex_unlock(&glk_data->abort_lock);
}
/* Internal function: shut down all requests and anything not necessary while
;
/* Wait for any pending window rearrange */
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
if(glk_data->needs_rearrange)
- g_cond_wait(glk_data->rearranged, glk_data->arrange_lock);
- g_mutex_unlock(glk_data->arrange_lock);
+ g_cond_wait(&glk_data->rearranged, &glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
}
/* Internal function: do any Glk-thread cleanup for shutting down the Glk library. */
glk_schannel_destroy(sch);
/* Empty the event queue */
- g_mutex_lock(glk_data->event_lock);
+ g_mutex_lock(&glk_data->event_lock);
g_queue_foreach(glk_data->event_queue, (GFunc)g_free, NULL);
/* COMPAT: g_queue_clear could be used here, but only appeared in 2.14 */
glk_data->event_queue->head = glk_data->event_queue->tail = NULL;
glk_data->event_queue->length = 0;
- g_mutex_unlock(glk_data->event_lock);
-
+ g_mutex_unlock(&glk_data->event_lock);
+
/* Reset the abort signaling mechanism */
- g_mutex_lock(glk_data->abort_lock);
+ g_mutex_lock(&glk_data->abort_lock);
glk_data->abort_signalled = FALSE;
- g_mutex_unlock(glk_data->abort_lock);
-
+ g_mutex_unlock(&glk_data->abort_lock);
+
/* Reset arrangement mechanism */
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
glk_data->needs_rearrange = FALSE;
glk_data->ignore_next_arrange_event = FALSE;
- g_mutex_unlock(glk_data->arrange_lock);
-
+ g_mutex_unlock(&glk_data->arrange_lock);
+
/* Unref input queues (they are not destroyed because the main thread stil holds a ref */
g_async_queue_unref(glk_data->char_input_queue);
g_async_queue_unref(glk_data->line_input_queue);
/* *** Threading data *** */
/* Whether program is running */
gboolean running;
+ /* Whether widget has been finalized */
+ gboolean after_finalize;
/* Glk program loaded in widget */
GModule *program;
/* Thread in which Glk program is run */
GThread *thread;
/* Event queue and threading stuff */
GQueue *event_queue;
- GMutex *event_lock;
- GCond *event_queue_not_empty;
- GCond *event_queue_not_full;
+ GMutex event_lock;
+ GCond event_queue_not_empty;
+ GCond event_queue_not_full;
/* Abort mechanism */
- GMutex *abort_lock;
+ GMutex abort_lock;
gboolean abort_signalled;
/* Key press after shutdown mechanism */
- GMutex *shutdown_lock;
- GCond *shutdown_key_pressed;
+ GMutex shutdown_lock;
+ GCond shutdown_key_pressed;
/* Window arrangement locks */
- GMutex *arrange_lock;
- GCond *rearranged;
+ GMutex arrange_lock;
+ GCond rearranged;
gboolean needs_rearrange;
gboolean ignore_next_arrange_event;
/* Input queues */
GAsyncQueue *char_input_queue;
GAsyncQueue *line_input_queue;
/* Resource loading locks */
- GMutex *resource_lock;
- GCond *resource_loaded;
- GCond *resource_info_available;
+ GMutex resource_lock;
+ GCond resource_loaded;
+ GCond resource_info_available;
guint32 resource_available;
/* *** Glk library data *** */
priv->glk_styles = g_new0(StyleSet,1);
priv->final_message = g_strdup("[ The game has finished ]");
priv->event_queue = g_queue_new();
- priv->event_lock = g_mutex_new();
- priv->event_queue_not_empty = g_cond_new();
- priv->event_queue_not_full = g_cond_new();
- priv->abort_lock = g_mutex_new();
- priv->shutdown_lock = g_mutex_new();
- priv->shutdown_key_pressed = g_cond_new();
- priv->arrange_lock = g_mutex_new();
- priv->rearranged = g_cond_new();
priv->char_input_queue = g_async_queue_new();
priv->line_input_queue = g_async_queue_new();
/* FIXME Should be g_async_queue_new_full(g_free); but only in GTK >= 2.16 */
- priv->resource_lock = g_mutex_new();
- priv->resource_loaded = g_cond_new();
- priv->resource_info_available = g_cond_new();
+
+ g_mutex_init(&priv->event_lock);
+ g_mutex_init(&priv->abort_lock);
+ g_mutex_init(&priv->shutdown_lock);
+ g_mutex_init(&priv->arrange_lock);
+ g_mutex_init(&priv->resource_lock);
+
+ g_cond_init(&priv->event_queue_not_empty);
+ g_cond_init(&priv->event_queue_not_full);
+ g_cond_init(&priv->shutdown_key_pressed);
+ g_cond_init(&priv->rearranged);
+ g_cond_init(&priv->resource_loaded);
+ g_cond_init(&priv->resource_info_available);
style_init(self);
}
{
ChimaraGlk *self = CHIMARA_GLK(object);
CHIMARA_GLK_USE_PRIVATE(self, priv);
+ priv->after_finalize = TRUE;
/* Free widget properties */
g_free(priv->final_message);
g_hash_table_destroy(priv->glk_styles->text_grid);
/* Free the event queue */
- g_mutex_lock(priv->event_lock);
+ g_mutex_lock(&priv->event_lock);
g_queue_foreach(priv->event_queue, (GFunc)g_free, NULL);
g_queue_free(priv->event_queue);
- g_cond_free(priv->event_queue_not_empty);
- g_cond_free(priv->event_queue_not_full);
+ g_cond_clear(&priv->event_queue_not_empty);
+ g_cond_clear(&priv->event_queue_not_full);
priv->event_queue = NULL;
- g_mutex_unlock(priv->event_lock);
- g_mutex_free(priv->event_lock);
+ g_mutex_unlock(&priv->event_lock);
+ g_mutex_clear(&priv->event_lock);
+
/* Free the abort signaling mechanism */
- g_mutex_lock(priv->abort_lock);
+ g_mutex_lock(&priv->abort_lock);
/* Make sure no other thread is busy with this */
- g_mutex_unlock(priv->abort_lock);
- g_mutex_free(priv->abort_lock);
- priv->abort_lock = NULL;
+ g_mutex_unlock(&priv->abort_lock);
+ g_mutex_clear(&priv->abort_lock);
+
/* Free the shutdown keypress signaling mechanism */
- g_mutex_lock(priv->shutdown_lock);
- g_cond_free(priv->shutdown_key_pressed);
- g_mutex_unlock(priv->shutdown_lock);
- priv->shutdown_lock = NULL;
+ g_mutex_lock(&priv->shutdown_lock);
+ g_cond_clear(&priv->shutdown_key_pressed);
+ g_mutex_unlock(&priv->shutdown_lock);
+ g_mutex_clear(&priv->shutdown_lock);
+
/* Free the window arrangement signaling */
- g_mutex_lock(priv->arrange_lock);
- g_cond_free(priv->rearranged);
- g_mutex_unlock(priv->arrange_lock);
- g_mutex_free(priv->arrange_lock);
- priv->arrange_lock = NULL;
- g_mutex_lock(priv->resource_lock);
- g_cond_free(priv->resource_loaded);
- g_cond_free(priv->resource_info_available);
- g_mutex_unlock(priv->resource_lock);
- g_mutex_free(priv->resource_lock);
+ g_mutex_lock(&priv->arrange_lock);
+ g_cond_clear(&priv->rearranged);
+ g_mutex_unlock(&priv->arrange_lock);
+ g_mutex_clear(&priv->arrange_lock);
+
+ g_mutex_lock(&priv->resource_lock);
+ g_cond_clear(&priv->resource_loaded);
+ g_cond_clear(&priv->resource_info_available);
+ g_mutex_unlock(&priv->resource_lock);
+ g_mutex_clear(&priv->resource_lock);
g_slist_foreach(priv->image_cache, (GFunc)clear_image_cache, NULL);
g_slist_free(priv->image_cache);
/* Unref input queues (this should destroy them since any Glk thread has stopped by now */
/* arrange points to a window that contains all text grid and graphics
windows which have been resized */
- g_mutex_lock(priv->arrange_lock);
+ g_mutex_lock(&priv->arrange_lock);
if(!priv->ignore_next_arrange_event)
{
if(arrange)
else
priv->ignore_next_arrange_event = FALSE;
priv->needs_rearrange = FALSE;
- g_cond_signal(priv->rearranged);
- g_mutex_unlock(priv->arrange_lock);
+ g_cond_signal(&priv->rearranged);
+ g_mutex_unlock(&priv->arrange_lock);
}
}
if(!priv->running)
return;
- if(priv->abort_lock) {
- g_mutex_lock(priv->abort_lock);
+ if(!priv->after_finalize) {
+ g_mutex_lock(&priv->abort_lock);
priv->abort_signalled = TRUE;
- g_mutex_unlock(priv->abort_lock);
+ g_mutex_unlock(&priv->abort_lock);
/* Stop blocking on the event queue condition */
event_throw(glk, evtype_Abort, NULL, 0, 0);
/* Stop blocking on the shutdown key press condition */
- g_mutex_lock(priv->shutdown_lock);
- g_cond_signal(priv->shutdown_key_pressed);
- g_mutex_unlock(priv->shutdown_lock);
+ g_mutex_lock(&priv->shutdown_lock);
+ g_cond_signal(&priv->shutdown_key_pressed);
+ g_mutex_unlock(&priv->shutdown_lock);
}
}
g_get_current_time(&timeout);
g_time_val_add(&timeout, EVENT_TIMEOUT_MICROSECONDS);
- g_mutex_lock(priv->event_lock);
+ g_mutex_lock(&priv->event_lock);
/* Wait for room in the event queue */
while( g_queue_get_length(priv->event_queue) >= EVENT_QUEUE_MAX_LENGTH )
- if( !g_cond_timed_wait(priv->event_queue_not_full, priv->event_lock, &timeout) )
+ if( !g_cond_timed_wait(&priv->event_queue_not_full, &priv->event_lock, &timeout) )
{
/* Drop the event after 3 seconds */
- g_mutex_unlock(priv->event_lock);
+ g_mutex_unlock(&priv->event_lock);
return;
}
g_queue_push_head(priv->event_queue, event);
/* Signal that there is an event */
- g_cond_signal(priv->event_queue_not_empty);
+ g_cond_signal(&priv->event_queue_not_empty);
- g_mutex_unlock(priv->event_lock);
+ g_mutex_unlock(&priv->event_lock);
}
/* Helper function: Wait for an event in the event queue. If it is a forced
get_appropriate_event(event_t *event)
{
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
-
- g_mutex_lock(glk_data->event_lock);
+
+ g_mutex_lock(&glk_data->event_lock);
event_t *retrieved_event = NULL;
/* Wait for an event */
if( g_queue_is_empty(glk_data->event_queue) )
- g_cond_wait(glk_data->event_queue_not_empty, glk_data->event_lock);
+ g_cond_wait(&glk_data->event_queue_not_empty, &glk_data->event_lock);
retrieved_event = g_queue_pop_tail(glk_data->event_queue);
/* Signal that the event queue is no longer full */
- g_cond_signal(glk_data->event_queue_not_full);
-
- g_mutex_unlock(glk_data->event_lock);
-
+ g_cond_signal(&glk_data->event_queue_not_full);
+
+ g_mutex_unlock(&glk_data->event_lock);
+
if(retrieved_event->type == evtype_ForcedCharInput)
{
/* Check for forced character input in the queue */
else
{
get_appropriate_event(event);
- g_mutex_lock(glk_data->event_lock);
+ g_mutex_lock(&glk_data->event_lock);
g_queue_push_tail(glk_data->event_queue, retrieved_event);
- g_cond_signal(glk_data->event_queue_not_empty);
- g_mutex_unlock(glk_data->event_lock);
+ g_cond_signal(&glk_data->event_queue_not_empty);
+ g_mutex_unlock(&glk_data->event_lock);
}
}
else if(retrieved_event->type == evtype_ForcedLineInput)
else
{
get_appropriate_event(event);
- g_mutex_lock(glk_data->event_lock);
+ g_mutex_lock(&glk_data->event_lock);
g_queue_push_tail(glk_data->event_queue, retrieved_event);
- g_cond_signal(glk_data->event_queue_not_empty);
- g_mutex_unlock(glk_data->event_lock);
+ g_cond_signal(&glk_data->event_queue_not_empty);
+ g_mutex_unlock(&glk_data->event_lock);
}
}
else
event->win = NULL;
event->val1 = 0;
event->val2 = 0;
-
- g_mutex_lock(glk_data->event_lock);
-
+
+ g_mutex_lock(&glk_data->event_lock);
+
if( !g_queue_is_empty(glk_data->event_queue) )
{
GList *link;
memcpy(event, link->data, sizeof(event_t));
g_free(link->data);
g_queue_delete_link(glk_data->event_queue, link);
- g_cond_signal(glk_data->event_queue_not_full);
+ g_cond_signal(&glk_data->event_queue_not_full);
break;
}
}
}
-
- g_mutex_unlock(glk_data->event_lock);
-
+
+ g_mutex_unlock(&glk_data->event_lock);
+
/* Check for interrupt */
glk_tick();
glk_put_string("\n");
flush_window_buffer(largewin);
}
-
- g_mutex_lock(glk_data->shutdown_lock);
+
+ g_mutex_lock(&glk_data->shutdown_lock);
for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL)) {
if(win->type == wintype_TextGrid || win->type == wintype_TextBuffer)
g_signal_handler_unblock(win->widget, win->shutdown_keypress_handler);
}
- g_cond_wait(glk_data->shutdown_key_pressed, glk_data->shutdown_lock);
- g_mutex_unlock(glk_data->shutdown_lock);
-
+ g_cond_wait(&glk_data->shutdown_key_pressed, &glk_data->shutdown_lock);
+ g_mutex_unlock(&glk_data->shutdown_lock);
+
shutdown_glk_post();
g_signal_emit_by_name(glk_data->self, "stopped");
g_free(buffer);
/* Wait for the PixbufLoader to finish loading the image */
- g_mutex_lock(glk_data->resource_lock);
+ g_mutex_lock(&glk_data->resource_lock);
while(!image_loaded) {
- g_cond_wait(glk_data->resource_loaded, glk_data->resource_lock);
+ g_cond_wait(&glk_data->resource_loaded, &glk_data->resource_lock);
}
- g_mutex_unlock(glk_data->resource_lock);
+ g_mutex_unlock(&glk_data->resource_lock);
info->pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
g_object_ref(info->pixbuf);
{
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
- g_mutex_lock(glk_data->resource_lock);
+ g_mutex_lock(&glk_data->resource_lock);
info->width = width;
info->height = height;
size_determined = TRUE;
- g_cond_broadcast(glk_data->resource_info_available);
- g_mutex_unlock(glk_data->resource_lock);
+ g_cond_broadcast(&glk_data->resource_info_available);
+ g_mutex_unlock(&glk_data->resource_lock);
}
void
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
- g_mutex_lock(glk_data->resource_lock);
+ g_mutex_lock(&glk_data->resource_lock);
image_loaded = TRUE;
- g_cond_broadcast(glk_data->resource_loaded);
- g_mutex_unlock(glk_data->resource_lock);
+ g_cond_broadcast(&glk_data->resource_loaded);
+ g_mutex_unlock(&glk_data->resource_lock);
gdk_threads_leave();
}
g_node_traverse(priv->root_window, G_IN_ORDER, G_TRAVERSE_LEAVES, -1, (GNodeTraverseFunc)turn_off_handler, NULL);
/* Signal the Glk library that it can shut everything down now */
- g_mutex_lock(priv->shutdown_lock);
- g_cond_signal(priv->shutdown_key_pressed);
- g_mutex_unlock(priv->shutdown_lock);
-
+ g_mutex_lock(&priv->shutdown_lock);
+ g_cond_signal(&priv->shutdown_key_pressed);
+ g_mutex_unlock(&priv->shutdown_lock);
+
return TRUE; /* block the event */
}
}
/* Set the window as a child of the Glk widget, don't trigger an arrange event */
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
glk_data->needs_rearrange = TRUE;
glk_data->ignore_next_arrange_event = TRUE;
- g_mutex_unlock(glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
gtk_widget_set_parent(win->frame, GTK_WIDGET(glk_data->self));
gtk_widget_queue_resize(GTK_WIDGET(glk_data->self));
window_close_common(win, FALSE);
/* Schedule a redraw */
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
glk_data->needs_rearrange = TRUE;
glk_data->ignore_next_arrange_event = TRUE;
- g_mutex_unlock(glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
gtk_widget_queue_resize( GTK_WIDGET(glk_data->self) );
gdk_threads_leave();
}
/* fill the buffer with blanks */
{
/* Wait for the window's size to be updated */
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
if(glk_data->needs_rearrange)
- g_cond_wait(glk_data->rearranged, glk_data->arrange_lock);
- g_mutex_unlock(glk_data->arrange_lock);
-
+ g_cond_wait(&glk_data->rearranged, &glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
+
gdk_threads_enter();
/* Manually put newlines at the end of each row of characters in the buffer; manual newlines make resizing the window's grid easier. */
GtkAllocation allocation;
/* Wait for the window's size to be updated */
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
if(glk_data->needs_rearrange)
- g_cond_wait(glk_data->rearranged, glk_data->arrange_lock);
- g_mutex_unlock(glk_data->arrange_lock);
+ g_cond_wait(&glk_data->rearranged, &glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
gdk_threads_enter();
gtk_widget_get_allocation(win->widget, &allocation);
case wintype_TextGrid:
/* Wait until the window's size is current */
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
if(glk_data->needs_rearrange)
- g_cond_wait(glk_data->rearranged, glk_data->arrange_lock);
- g_mutex_unlock(glk_data->arrange_lock);
-
+ g_cond_wait(&glk_data->rearranged, &glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
+
gdk_threads_enter();
gtk_widget_get_allocation(win->widget, &allocation);
/* Cache the width and height */
break;
case wintype_TextBuffer:
- /* Wait until the window's size is current */
- g_mutex_lock(glk_data->arrange_lock);
+ /* Wait until the window's size is current */
+ g_mutex_lock(&glk_data->arrange_lock);
if(glk_data->needs_rearrange)
- g_cond_wait(glk_data->rearranged, glk_data->arrange_lock);
- g_mutex_unlock(glk_data->arrange_lock);
-
+ g_cond_wait(&glk_data->rearranged, &glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
+
gdk_threads_enter();
gtk_widget_get_allocation(win->widget, &allocation);
if(widthptr != NULL)
break;
case wintype_Graphics:
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
if(glk_data->needs_rearrange)
- g_cond_wait(glk_data->rearranged, glk_data->arrange_lock);
- g_mutex_unlock(glk_data->arrange_lock);
-
+ g_cond_wait(&glk_data->rearranged, &glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
+
gdk_threads_enter();
gtk_widget_get_allocation(win->widget, &allocation);
if(widthptr != NULL)
/* Tell GTK to rearrange the windows */
gdk_threads_enter();
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
glk_data->needs_rearrange = TRUE;
glk_data->ignore_next_arrange_event = TRUE;
- g_mutex_unlock(glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
gtk_widget_queue_resize(GTK_WIDGET(glk_data->self));
gdk_threads_leave();
}
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
/* Wait until the window's size is current */
- g_mutex_lock(glk_data->arrange_lock);
+ g_mutex_lock(&glk_data->arrange_lock);
if(glk_data->needs_rearrange)
- g_cond_wait(glk_data->rearranged, glk_data->arrange_lock);
- g_mutex_unlock(glk_data->arrange_lock);
+ g_cond_wait(&glk_data->rearranged, &glk_data->arrange_lock);
+ g_mutex_unlock(&glk_data->arrange_lock);
/* Don't do anything if the window is shrunk down to nothing */
if(win->width == 0 || win->height == 0)