📄 st-thread.c
字号:
/* * Copyright (c) 2002, 2003, 2004 Jean-Yves Lefort * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include <stdlib.h>#include <stdarg.h>#include <glib.h>#include <glib/gi18n.h>#include "st-dialog-api.h"#include "st-thread.h"#include "st-handler.h"/*** type definitions ********************************************************/struct _STThreadPrivate{ gboolean aborted; GMutex *aborted_mutex; gboolean cleaned_up; GTimer *print_timer; GTimer *set_progress_timer;};/*** function declarations ***************************************************/static gpointer st_thread_cb (gpointer data);static gboolean st_thread_time (STThread *thread, GTimer **timer, gboolean force);/*** implementation **********************************************************/voidst_thread_init (void){ g_thread_init(NULL); if (! g_thread_supported()) { /* * We can't use st_error_dialog() because gtk_init() has not * been called yet. */ st_notice(_("fatal error: the GLib thread system is unavailable")); exit(1); } gdk_threads_init();}STThread *st_thread_new (STHandler *handler){ STThread *thread; thread = g_new0(STThread, 1); thread->handler = handler; thread->priv = g_new0(STThreadPrivate, 1); thread->priv->aborted_mutex = g_mutex_new(); return thread;}voidst_thread_run (STThread *thread){ GError *err = NULL; g_return_if_fail(thread != NULL); g_return_if_fail(thread->thread != NULL); /* * libcurl uses a 64k stack buffer for decompression operations. * * On some platforms, the default thread stack size might not be * large enough, so we use a 96k stack (for instance, the default * thread stack size on FreeBSD is 64k). */ if (! g_thread_create_full(st_thread_cb, thread, 0x18000, /* 96k, big enough for libcurl */ FALSE, FALSE, G_THREAD_PRIORITY_NORMAL, &err)) { char *secondary; char *normalized; secondary = g_strdup_printf(_("Unable to create a thread: %s"), err->message); normalized = st_dialog_normalize(secondary); st_error_dialog(_("A fatal error has occurred"), "%s", normalized); g_free(secondary); g_free(normalized); g_error_free(err); exit(1); }}static gpointerst_thread_cb (gpointer data){ STThread *thread = data; gpointer thread_data = NULL; g_return_val_if_fail(thread != NULL, NULL); g_return_val_if_fail(thread->thread != NULL, NULL); if (st_handler_event_is_bound(thread->handler, ST_HANDLER_EVENT_THREAD_BEGIN)) thread_data = st_handler_event_thread_begin(thread->handler); thread->thread(thread->data); if (! thread->priv->cleaned_up) { GDK_THREADS_ENTER(); st_thread_cleanup(thread); gdk_flush(); GDK_THREADS_LEAVE(); } if (thread->data_destroy) thread->data_destroy(thread->data); if (st_handler_event_is_bound(thread->handler, ST_HANDLER_EVENT_THREAD_END)) st_handler_event_thread_end(thread->handler, thread_data); /* free ourselves */ g_mutex_free(thread->priv->aborted_mutex); if (thread->priv->print_timer) g_timer_destroy(thread->priv->print_timer); if (thread->priv->set_progress_timer) g_timer_destroy(thread->priv->set_progress_timer); g_free(thread->priv); g_free(thread); return NULL;}static gbooleanst_thread_time (STThread *thread, GTimer **timer, gboolean force){ gboolean go_on = force; g_return_val_if_fail(thread != NULL, FALSE); g_return_val_if_fail(timer != NULL, FALSE); if (! *timer) { *timer = g_timer_new(); go_on = TRUE; } if (! go_on) go_on = g_timer_elapsed(*timer, 0) > 0.1; if (go_on) g_timer_start(*timer); return go_on;}STThread *st_thread_get (void){ GThread *g_thread; g_thread = g_thread_self(); return g_thread ? g_thread->data : NULL;}voidst_thread_printf (STThread *thread, gboolean force, const char *format, ...){ g_return_if_fail(thread != NULL); g_return_if_fail(format != NULL); if (thread->print && st_thread_time(thread, &thread->priv->print_timer, force)) { va_list args; char *str; va_start(args, format); str = g_strdup_vprintf(format, args); va_end(args); thread->print(str, thread->data); g_free(str); }}voidst_thread_set_progress (STThread *thread, gboolean force, double progress){ g_return_if_fail(thread != NULL); if (thread->set_progress && st_thread_time(thread, &thread->priv->set_progress_timer, force)) thread->set_progress(progress, thread->data);}voidst_thread_forget (STThread *thread){ g_return_if_fail(thread != NULL); g_mutex_lock(thread->priv->aborted_mutex); thread->priv->aborted = TRUE; g_mutex_unlock(thread->priv->aborted_mutex);}voidst_thread_abort (STThread *thread){ g_return_if_fail(thread != NULL); st_thread_forget(thread); st_thread_cleanup(thread);}gbooleanst_thread_is_aborted (STThread *thread){ gboolean aborted; g_return_val_if_fail(thread != NULL, FALSE); g_mutex_lock(thread->priv->aborted_mutex); aborted = thread->priv->aborted; g_mutex_unlock(thread->priv->aborted_mutex); return aborted;}voidst_thread_cleanup (STThread *thread){ g_return_if_fail(thread != NULL); if (! thread->priv->cleaned_up) { if (thread->cleanup) thread->cleanup(thread->data); thread->priv->cleaned_up = TRUE; }}voidst_thread_validate_callback_return (STThread *thread, gboolean status, GError *err){ g_return_if_fail(thread != NULL); if (st_thread_is_aborted(thread)) { if (err) st_error_dialog(_("A callback error has occurred"), _("The task was aborted but the callback reported that there was an error.")); } else { if (! status && ! err) { /* do what was supposed to have been done */ GDK_THREADS_ENTER(); st_thread_abort(thread); gdk_flush(); GDK_THREADS_LEAVE(); st_error_dialog(_("A callback error has occurred"), _("The callback reported that the task was aborted but it was not.")); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -