From a75654a326dadebacc229762eb01f5e7c65b1ccc Mon Sep 17 00:00:00 2001 From: hiro Date: Tue, 29 Sep 2009 07:49:30 +0000 Subject: made GDK locks reentrant, and made LogWindow thread-safe. git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@2259 ee746299-78ed-0310-b773-934348b2243d --- src/inc.c | 1 + src/logwindow.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/logwindow.h | 9 ++++++- src/main.c | 30 ++++++++++++++++++--- src/send_message.c | 1 + src/statusbar.c | 2 ++ 6 files changed, 115 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/inc.c b/src/inc.c index 2a55fe2c..5dfbd8af 100644 --- a/src/inc.c +++ b/src/inc.c @@ -865,6 +865,7 @@ static IncState inc_pop3_session_do(IncSession *session) session->inc_state != INC_CANCEL) { gtk_main_iteration(); } + log_window_flush(); if (session->inc_state == INC_SUCCESS) { switch (pop3_session->error_val) { diff --git a/src/logwindow.c b/src/logwindow.c index 017bb37b..beab32a8 100644 --- a/src/logwindow.c +++ b/src/logwindow.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto + * Copyright (C) 1999-2009 Hiroyuki Yamamoto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +41,10 @@ static LogWindow *logwindow; +#if USE_THREADS +static GThread *main_thread; +#endif + static void log_window_print_func (const gchar *str); static void log_window_message_func (const gchar *str); static void log_window_warning_func (const gchar *str); @@ -99,6 +103,13 @@ LogWindow *log_window_create(void) logwin->text = text; logwin->lines = 1; +#if USE_THREADS + logwin->aqueue = g_async_queue_new(); + + main_thread = g_thread_self(); + debug_print("main_thread = %p\n", main_thread); +#endif + logwindow = logwin; return logwin; @@ -160,7 +171,7 @@ void log_window_show(LogWindow *logwin) gtk_window_present(GTK_WINDOW(logwin->window)); } -void log_window_append(const gchar *str, LogType type) +static void log_window_append_real(const gchar *str, LogType type) { GtkTextView *text; GtkTextBuffer *buffer; @@ -172,6 +183,14 @@ void log_window_append(const gchar *str, LogType type) g_return_if_fail(logwindow != NULL); +#if USE_THREADS + if (g_thread_self() != main_thread) { + return; + } +#endif + + gdk_threads_enter(); + text = GTK_TEXT_VIEW(logwindow->text); buffer = gtk_text_view_get_buffer(text); @@ -233,6 +252,61 @@ void log_window_append(const gchar *str, LogType type) } logwindow->lines++; + + gdk_threads_leave(); +} + +void log_window_append(const gchar *str, LogType type) +{ +#if USE_THREADS + if (g_thread_self() != main_thread) { + fprintf(stderr, "log_window_append called from non-main thread (%p)\n", g_thread_self()); + log_window_append_queue(str, type); + return; + } + + log_window_flush(); +#endif + log_window_append_real(str, type); +} + +typedef struct _LogData +{ + gchar *str; + LogType type; +} LogData; + +void log_window_append_queue(const gchar *str, LogType type) +{ +#if USE_THREADS + LogData *logdata; + + logdata = g_new(LogData, 1); + logdata->str = g_strdup(str); + logdata->type = type; + + g_print("append_queue: (%d) %s\n", type, str); + g_async_queue_push(logwindow->aqueue, logdata); +#endif +} + +void log_window_flush(void) +{ +#if USE_THREADS + LogData *logdata; + + if (g_thread_self() != main_thread) { + fprintf(stderr, "log_window_flush called from non-main thread (%p)\n", g_thread_self()); + return; + } + + while ((logdata = g_async_queue_try_pop(logwindow->aqueue))) { + g_print("flush_queue: (%d) %s\n", logdata->type, logdata->str); + log_window_append_real(logdata->str, logdata->type); + g_free(logdata->str); + g_free(logdata); + } +#endif } static void log_window_print_func(const gchar *str) diff --git a/src/logwindow.h b/src/logwindow.h index 97a9159f..7e4a1d47 100644 --- a/src/logwindow.h +++ b/src/logwindow.h @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2003 Hiroyuki Yamamoto + * Copyright (C) 1999-2009 Hiroyuki Yamamoto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,6 +44,10 @@ struct _LogWindow GdkColor error_color; gint lines; + +#if USE_THREADS + GAsyncQueue *aqueue; +#endif }; LogWindow *log_window_create(void); @@ -51,5 +55,8 @@ void log_window_init(LogWindow *logwin); void log_window_show(LogWindow *logwin); void log_window_append(const gchar *str, LogType type); +void log_window_append_queue(const gchar *str, LogType type); + +void log_window_flush(void); #endif /* __LOGWINDOW_H__ */ diff --git a/src/main.c b/src/main.c index 82937164..af686954 100644 --- a/src/main.c +++ b/src/main.c @@ -580,11 +580,32 @@ static gint get_queued_message_num(void) } #if USE_THREADS +/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */ +static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT; + +static void thread_enter_func(void) +{ + g_static_rec_mutex_lock(&syl_mutex); +#if 0 + syl_mutex_lock_count++; + if (syl_mutex_lock_count > 1) + g_print("enter: syl_mutex_lock_count: %d\n", syl_mutex_lock_count); +#endif +} + +static void thread_leave_func(void) +{ +#if 0 + syl_mutex_lock_count--; + if (syl_mutex_lock_count > 0) + g_print("leave: syl_mutex_lock_count: %d\n", syl_mutex_lock_count); +#endif + g_static_rec_mutex_unlock(&syl_mutex); +} + static void event_loop_iteration_func(void) { - //g_print("event_loop_iteration_func start\n"); gtk_main_iteration(); - //g_print("event_loop_iteration_func end\n"); } #endif @@ -595,8 +616,11 @@ static void app_init(void) g_thread_init(NULL); if (!g_thread_supported()) g_error("g_thread is not supported by glib."); - else + else { + gdk_threads_set_lock_functions(thread_enter_func, + thread_leave_func); gdk_threads_init(); + } #endif syl_init(); diff --git a/src/send_message.c b/src/send_message.c index c44232d4..e2527292 100644 --- a/src/send_message.c +++ b/src/send_message.c @@ -747,6 +747,7 @@ static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp) while (session_is_connected(session) && dialog->cancelled == FALSE) gtk_main_iteration(); + log_window_flush(); if (SMTP_SESSION(session)->error_val == SM_AUTHFAIL) { if (ac_prefs->smtp_userid && ac_prefs->tmp_smtp_pass) { diff --git a/src/statusbar.c b/src/statusbar.c index c4f7a6d4..2bd7ff8d 100644 --- a/src/statusbar.c +++ b/src/statusbar.c @@ -67,8 +67,10 @@ void statusbar_puts_all(const gchar *str) { GList *cur; + gdk_threads_enter(); for (cur = statusbar_list; cur != NULL; cur = cur->next) statusbar_puts(GTK_STATUSBAR(cur->data), str); + gdk_threads_leave(); } void statusbar_print(GtkStatusbar *statusbar, const gchar *format, ...) -- cgit v1.2.3