X-Git-Url: https://git.stderr.nl/gitweb?p=rodin%2Fchimara.git;a=blobdiff_plain;f=libchimara%2Fabort.c;h=28e33fae444c5d85e64b29232d3b08d58b99572e;hp=8399f054901376b1d1790bc2639d5c4a27c330cc;hb=4b0bbd6bb235b4cad89d321cdd7f570610a97712;hpb=5bec9bc0e9bea45cd553116e5d7fd125564d8dbe diff --git a/libchimara/abort.c b/libchimara/abort.c index 8399f05..28e33fa 100644 --- a/libchimara/abort.c +++ b/libchimara/abort.c @@ -43,7 +43,13 @@ abort_glk(void) ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); if(glk_data->interrupt_handler) (*(glk_data->interrupt_handler))(); - shutdown_glk(); + shutdown_glk_pre(); + shutdown_glk_post(); + /* If program is terminated by g_thread_exit() instead of returning from the + glk_main() function, then the line in glk_enter() where the "stopped" + signal is emitted will not be reached. So we have to emit it here. */ + if(!glk_data->in_startup) + g_signal_emit_by_name(glk_data->self, "stopped"); g_thread_exit(NULL); } @@ -61,15 +67,16 @@ check_for_abort(void) g_mutex_unlock(glk_data->abort_lock); } -/* Internal function: do any cleanup for shutting down the Glk library. */ +/* Internal function: shut down all requests and anything not necessary while + showing the last displayed configuration of windows. */ void -shutdown_glk(void) +shutdown_glk_pre(void) { ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); - + /* Stop any timers */ glk_request_timer_events(0); - + /* Cancel any pending input requests and flush all window buffers */ winid_t win; for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL)) @@ -86,33 +93,83 @@ shutdown_glk(void) break; case INPUT_REQUEST_NONE: default: - ; /* Handle mouse and hyperlink requests */ + ; /* TODO: Handle mouse and hyperlink requests */ } - + flush_window_buffer(win); } - + /* Close any open resource files */ if(glk_data->resource_map != NULL) { giblorb_destroy_map(glk_data->resource_map); + glk_data->resource_map = NULL; glk_stream_close(glk_data->resource_file, NULL); } - - /* Unref the input queues */ - g_async_queue_unref(glk_data->char_input_queue); - g_async_queue_unref(glk_data->line_input_queue); - + + /* Empty the input queues */ + while(g_async_queue_try_pop(glk_data->char_input_queue)) + ; + while(g_async_queue_try_pop(glk_data->line_input_queue)) + ; + /* Wait for any pending window rearrange */ 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); +} - /* Default handler for 'stopped' unloads the plugin, so be absolutely sure - we're not calling any dispatch callbacks after this point */ - if(!glk_data->in_startup) - g_signal_emit_by_name(glk_data->self, "stopped"); +/* Internal function: do any Glk-thread cleanup for shutting down the Glk library. */ +void +shutdown_glk_post(void) +{ + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + + /* Free all opaque objects; can't iterate normally, because the objects are + being removed from the global iteration lists */ + if(glk_data->root_window) + glk_window_close(glk_data->root_window->data, NULL); + g_assert(glk_data->root_window == NULL); + strid_t str; + while( (str = glk_stream_iterate(NULL, NULL)) ) + glk_stream_close(str, NULL); + frefid_t fref; + while( (fref = glk_fileref_iterate(NULL, NULL)) ) + glk_fileref_destroy(fref); + schanid_t sch; + while( (sch = glk_schannel_iterate(NULL, NULL)) ) + glk_schannel_destroy(sch); + + /* Empty the event queue */ + g_mutex_lock(glk_data->event_lock); + g_queue_foreach(glk_data->event_queue, (GFunc)g_free, NULL); + g_queue_clear(glk_data->event_queue); + g_mutex_unlock(glk_data->event_lock); + + /* Reset the abort signaling mechanism */ + g_mutex_lock(glk_data->abort_lock); + glk_data->abort_signalled = FALSE; + g_mutex_unlock(glk_data->abort_lock); + + /* Reset arrangement mechanism */ + 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); + + /* 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); + + /* Reset other stuff */ + glk_data->interrupt_handler = NULL; + g_free(glk_data->current_dir); + glk_data->current_dir = NULL; + /* Remove the dispatch callbacks */ + glk_data->register_obj = NULL; + glk_data->unregister_obj = NULL; + glk_data->register_arr = NULL; + glk_data->unregister_arr = NULL; - _chimara_glk_free_nonwindow_private_data(glk_data); - glk_data->needs_reset = TRUE; + /* Leave the style_initialized flag as it is, since the CSS file is a widget property */ }