aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2009-09-17 07:26:17 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2009-09-17 07:26:17 +0000
commit71f191b2a609e291a3afcf726ab8aacab572637b (patch)
treefa744ee9944df82548c6afb33451455c4ce7c61a
parent24c2edfeacce97b6e4c3783c53cbd2532088af95 (diff)
introduced multi-threading.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@2255 ee746299-78ed-0310-b773-934348b2243d
-rw-r--r--ChangeLog19
-rw-r--r--libsylph/filter.c2
-rw-r--r--libsylph/session.c12
-rw-r--r--libsylph/socket.c78
-rw-r--r--libsylph/socket.h3
-rw-r--r--libsylph/utils.c56
-rw-r--r--libsylph/utils.h3
-rw-r--r--src/compose.c4
-rw-r--r--src/folderview.c15
-rw-r--r--src/inc.c5
-rw-r--r--src/main.c21
-rw-r--r--src/rpop3.c4
-rw-r--r--src/send_message.c11
-rw-r--r--src/sigstatus.c4
-rw-r--r--src/trayicon.c3
15 files changed, 227 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index e9751409..10f83faa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2009-09-18
+
+ * introduced multi-threading.
+ * libsylph/session.c
+ libsylph/socket.[ch]: win32: connect() on another thread to avoid
+ UI blocking.
+ * libsylph/filter.c
+ libsylph/utils.[ch]: execute command on another thread to avoid
+ UI blocking.
+ * src/rpop3.c
+ src/compose.c
+ src/inc.c
+ src/trayicon.c
+ src/main.c
+ src/send_message.c
+ src/folderview.c
+ src/sigstatus.c: surround timeout/IO-watch callback functions with
+ gdk_threads_enter() and gdk_threads_leave().
+
2009-09-17
* folderview_new_folder_cb(): win32: fixed prohibited character check.
diff --git a/libsylph/filter.c b/libsylph/filter.c
index 9ea834ff..e61b5095 100644
--- a/libsylph/filter.c
+++ b/libsylph/filter.c
@@ -400,7 +400,7 @@ static gboolean filter_match_cond(FilterCond *cond, MsgInfo *msginfo,
if (!file)
return FALSE;
cmdline = g_strconcat(cond->str_value, " \"", file, "\"", NULL);
- ret = execute_command_line(cmdline, FALSE);
+ ret = execute_command_line_async_wait(cmdline);
matched = (ret == 0);
if (ret == -1)
fltinfo->error = FLT_ERROR_EXEC_FAILED;
diff --git a/libsylph/session.c b/libsylph/session.c
index d64fc72d..0617e402 100644
--- a/libsylph/session.c
+++ b/libsylph/session.c
@@ -120,7 +120,8 @@ void session_init(Session *session)
gint session_connect(Session *session, const gchar *server, gushort port)
{
#ifndef G_OS_UNIX
- SockInfo *sock;
+ SockInfo *sock = NULL;
+ gint flag = 0;
#endif
g_return_val_if_fail(session != NULL, -1);
g_return_val_if_fail(server != NULL, -1);
@@ -143,8 +144,13 @@ gint session_connect(Session *session, const gchar *server, gushort port)
return 0;
#else
- sock = sock_connect(server, port);
- if (sock == NULL) {
+ session->conn_id = sock_connect_async(server, port);
+ if (session->conn_id < 0) {
+ g_warning("can't connect to server.");
+ session->state = SESSION_ERROR;
+ return -1;
+ }
+ if (sock_connect_async_wait(session->conn_id, &sock) < 0) {
g_warning("can't connect to server.");
session->state = SESSION_ERROR;
return -1;
diff --git a/libsylph/socket.c b/libsylph/socket.c
index 97d273d7..431d95f1 100644
--- a/libsylph/socket.c
+++ b/libsylph/socket.c
@@ -81,11 +81,17 @@ struct _SockConnectData {
gint id;
gchar *hostname;
gushort port;
+#ifdef G_OS_UNIX
GList *addr_list;
GList *cur_addr;
SockLookupData *lookup_data;
GIOChannel *channel;
guint io_tag;
+#else
+ gint flag;
+ GThread *thread;
+ SockInfo *sock;
+#endif
SockConnectFunc func;
gpointer data;
};
@@ -1317,6 +1323,78 @@ static gint sock_get_address_info_async_cancel(SockLookupData *lookup_data)
return 0;
}
+#else /* G_OS_UNIX */
+
+gpointer sock_connect_async_func(gpointer data)
+{
+ SockConnectData *conn_data = (SockConnectData *)data;
+
+ g_print("sock_connect_async_func: connect\n");
+ conn_data->sock = sock_connect(conn_data->hostname, conn_data->port);
+ conn_data->flag = 1;
+
+ g_print("sock_connect_async_func: connected\n");
+ g_main_context_wakeup(NULL);
+
+ return GINT_TO_POINTER(0);
+}
+
+gint sock_connect_async(const gchar *hostname, gushort port)
+{
+ static gint id = 1;
+ SockConnectData *data;
+
+ data = g_new0(SockConnectData, 1);
+ data->id = id++;
+ data->hostname = g_strdup(hostname);
+ data->port = port;
+ data->flag = 0;
+
+ data->thread = g_thread_create(sock_connect_async_func, data, TRUE,
+ NULL);
+ if (!data->thread) {
+ g_free(data->hostname);
+ g_free(data);
+ return -1;
+ }
+
+ sock_connect_data_list = g_list_append(sock_connect_data_list, data);
+
+ return data->id;
+}
+
+gint sock_connect_async_wait(gint id, SockInfo **sock)
+{
+ SockConnectData *conn_data = NULL;
+ GList *cur;
+
+ for (cur = sock_connect_data_list; cur != NULL; cur = cur->next) {
+ if (((SockConnectData *)cur->data)->id == id) {
+ conn_data = (SockConnectData *)cur->data;
+ break;
+ }
+ }
+
+ if (!conn_data) {
+ g_warning("sock_connect_async_wait: id %d not found.", id);
+ return -1;
+ }
+
+ g_print("sock_connect_async_wait: waiting thread\n");
+ while (conn_data->flag == 0)
+ g_main_context_iteration(NULL, TRUE);
+
+ g_print("sock_connect_async_wait: flagged\n");
+ g_thread_join(conn_data->thread);
+ g_print("sock_connect_async_wait: thread exited\n");
+
+ *sock = conn_data->sock;
+
+ sock_connect_data_list = g_list_remove(sock_connect_data_list,
+ conn_data);
+ g_free(conn_data->hostname);
+ g_free(conn_data);
+}
#endif /* G_OS_UNIX */
diff --git a/libsylph/socket.h b/libsylph/socket.h
index 5bf8b98f..0ddf0374 100644
--- a/libsylph/socket.h
+++ b/libsylph/socket.h
@@ -103,6 +103,9 @@ SockInfo *sock_connect (const gchar *hostname, gushort port);
gint sock_connect_async (const gchar *hostname, gushort port,
SockConnectFunc func, gpointer data);
gint sock_connect_async_cancel (gint id);
+#else
+gint sock_connect_async (const gchar *hostname, gushort port);
+gint sock_connect_async_wait (gint id, SockInfo **sock);
#endif
/* Basic I/O functions */
diff --git a/libsylph/utils.c b/libsylph/utils.c
index 574f8427..0139302e 100644
--- a/libsylph/utils.c
+++ b/libsylph/utils.c
@@ -3862,6 +3862,62 @@ gint execute_command_line(const gchar *cmdline, gboolean async)
return ret;
}
+typedef struct _CmdData
+{
+ const gchar *cmdline;
+ gint flag;
+ gint status;
+} CmdData;
+
+static gpointer execute_command_line_async_func(gpointer data)
+{
+ CmdData *cmd_data = (CmdData *)data;
+ gchar **argv;
+
+ g_print("execute_command_line_async_func\n");
+ argv = strsplit_with_quote(cmd_data->cmdline, " ", 0);
+ cmd_data->status = execute_sync(argv);
+ g_strfreev(argv);
+
+ g_print("execute_command_line_async_func: exec done.\n");
+ cmd_data->flag = 1;
+ g_main_context_wakeup(NULL);
+
+ return GINT_TO_POINTER(0);
+}
+
+gint execute_command_line_async_wait(const gchar *cmdline)
+{
+ volatile CmdData data = {NULL, 0, 0};
+ GThread *thread;
+
+ if (debug_mode) {
+ gchar *utf8_cmdline;
+
+ utf8_cmdline = g_filename_to_utf8
+ (cmdline, -1, NULL, NULL, NULL);
+ debug_print("execute_command_line(): executing: %s\n",
+ utf8_cmdline ? utf8_cmdline : cmdline);
+ g_free(utf8_cmdline);
+ }
+
+ data.cmdline = cmdline;
+ thread = g_thread_create(execute_command_line_async_func, &data, TRUE,
+ NULL);
+ if (!thread)
+ return -1;
+
+ g_print("execute_command_line_async_wait: waiting thread\n");
+ while (data.flag == 0)
+ g_main_context_iteration(NULL, TRUE);
+
+ g_print("execute_command_line_async_wait: flagged\n");
+ g_thread_join(thread);
+ g_print("execute_command_line_async_wait: thread exited\n");
+
+ return data.status;
+}
+
gint execute_open_file(const gchar *file, const gchar *content_type)
{
g_return_val_if_fail(file != NULL, -1);
diff --git a/libsylph/utils.h b/libsylph/utils.h
index 97221fb9..3bbc42cb 100644
--- a/libsylph/utils.h
+++ b/libsylph/utils.h
@@ -469,6 +469,9 @@ gint execute_async (gchar *const argv[]);
gint execute_sync (gchar *const argv[]);
gint execute_command_line (const gchar *cmdline,
gboolean async);
+gint execute_command_line_async_wait
+ (const gchar *cmdline);
+
gint execute_open_file (const gchar *file,
const gchar *content_type);
gint execute_print_file (const gchar *file);
diff --git a/src/compose.c b/src/compose.c
index 69ec4844..c24729d7 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -7777,10 +7777,14 @@ static gboolean autosave_timeout(gpointer data)
{
Compose *compose = (Compose *)data;
+ gdk_threads_enter();
+
debug_print("auto-saving...\n");
if (compose->modified)
compose_draft_cb(data, 1, NULL);
+ gdk_threads_leave();
+
return TRUE;
}
diff --git a/src/folderview.c b/src/folderview.c
index f938e5c1..b0976750 100644
--- a/src/folderview.c
+++ b/src/folderview.c
@@ -3001,6 +3001,9 @@ static gint auto_expand_timeout(gpointer data)
FolderView *folderview = data;
GtkTreeView *treeview = GTK_TREE_VIEW(folderview->treeview);
GtkTreePath *path = NULL;
+ gint ret;
+
+ gdk_threads_enter();
gtk_tree_view_get_drag_dest_row(treeview, &path, NULL);
@@ -3009,9 +3012,13 @@ static gint auto_expand_timeout(gpointer data)
gtk_tree_path_free(path);
folderview->expand_timeout = 0;
- return FALSE;
+ ret = FALSE;
} else
- return TRUE;
+ ret = TRUE;
+
+ gdk_threads_leave();
+
+ return ret;
}
static void remove_auto_expand_timeout(FolderView *folderview)
@@ -3026,9 +3033,13 @@ static gint auto_scroll_timeout(gpointer data)
{
FolderView *folderview = data;
+ gdk_threads_enter();
+
gtkut_tree_view_vertical_autoscroll
(GTK_TREE_VIEW(folderview->treeview));
+ gdk_threads_leave();
+
return TRUE;
}
diff --git a/src/inc.c b/src/inc.c
index 2e038d50..b9641b3b 100644
--- a/src/inc.c
+++ b/src/inc.c
@@ -1564,13 +1564,18 @@ static gint inc_autocheck_func(gpointer data)
{
MainWindow *mainwin = (MainWindow *)data;
+ gdk_threads_enter();
+
if (inc_lock_count) {
debug_print("autocheck is locked.\n");
inc_autocheck_timer_set_interval(1000);
+ gdk_threads_leave();
return FALSE;
}
inc_all_account_mail(mainwin, TRUE);
+ gdk_threads_leave();
+
return FALSE;
}
diff --git a/src/main.c b/src/main.c
index d012c90b..cb14d223 100644
--- a/src/main.c
+++ b/src/main.c
@@ -208,6 +208,9 @@ int main(int argc, char *argv[])
return 0;
}
+#if USE_THREADS
+ gdk_threads_enter();
+#endif
gtk_set_locale();
gtk_init(&argc, &argv);
@@ -217,13 +220,6 @@ int main(int argc, char *argv[])
gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
gtk_widget_set_default_visual(gdk_rgb_get_visual());
-#if USE_THREADS || USE_LDAP
- if (!g_thread_supported())
- g_thread_init(NULL);
- if (!g_thread_supported())
- g_error(_("g_thread is not supported by glib.\n"));
-#endif
-
parse_gtkrc_files();
setup_rc_dir();
@@ -341,6 +337,9 @@ int main(int argc, char *argv[])
update_check(FALSE);
gtk_main();
+#if USE_THREADS
+ gdk_threads_leave();
+#endif
return 0;
}
@@ -582,6 +581,14 @@ static gint get_queued_message_num(void)
static void app_init(void)
{
+#if USE_THREADS
+ if (!g_thread_supported())
+ g_thread_init(NULL);
+ if (!g_thread_supported())
+ g_error("g_thread is not supported by glib.");
+ else
+ gdk_threads_init();
+#endif
syl_init();
prog_version = PROG_VERSION;
diff --git a/src/rpop3.c b/src/rpop3.c
index 347f1a83..aee98956 100644
--- a/src/rpop3.c
+++ b/src/rpop3.c
@@ -608,6 +608,8 @@ static void rpop3_clear_list(void)
static gboolean rpop3_ping_cb(gpointer data)
{
+ gdk_threads_enter();
+
if (rpop3_window.ping_tag > 0) {
g_source_remove(rpop3_window.ping_tag);
rpop3_window.ping_tag = 0;
@@ -615,6 +617,8 @@ static gboolean rpop3_ping_cb(gpointer data)
if (rpop3_window.session->state == POP3_IDLE)
rpop3_noop_send(rpop3_window.session);
+ gdk_threads_leave();
+
return FALSE;
}
diff --git a/src/send_message.c b/src/send_message.c
index db474602..c44232d4 100644
--- a/src/send_message.c
+++ b/src/send_message.c
@@ -795,9 +795,12 @@ static gint send_recv_message(Session *session, const gchar *msg, gpointer data)
g_return_val_if_fail(dialog != NULL, -1);
+ gdk_threads_enter();
+
switch (smtp_session->state) {
case SMTP_READY:
case SMTP_CONNECTED:
+ gdk_threads_leave();
return 0;
case SMTP_HELO:
g_snprintf(buf, sizeof(buf), _("Sending HELO..."));
@@ -832,14 +835,18 @@ static gint send_recv_message(Session *session, const gchar *msg, gpointer data)
break;
case SMTP_ERROR:
g_warning("send: error: %s\n", msg);
+ gdk_threads_leave();
return 0;
default:
+ gdk_threads_leave();
return 0;
}
progress_dialog_set_label(dialog->dialog, buf);
progress_dialog_set_row_status(dialog->dialog, 0, state_str);
+ gdk_threads_leave();
+
return 0;
}
@@ -855,6 +862,8 @@ static gint send_send_data_progressive(Session *session, guint cur_len,
SMTP_SESSION(session)->state != SMTP_EOM)
return 0;
+ gdk_threads_enter();
+
g_snprintf(buf, sizeof(buf), _("Sending message (%d / %d bytes)"),
cur_len, total_len);
progress_dialog_set_label(dialog->dialog, buf);
@@ -866,6 +875,7 @@ static gint send_send_data_progressive(Session *session, guint cur_len,
#ifdef G_OS_WIN32
GTK_EVENTS_FLUSH();
#endif
+ gdk_threads_leave();
return 0;
}
@@ -877,6 +887,7 @@ static gint send_send_data_finished(Session *session, guint len, gpointer data)
g_return_val_if_fail(dialog != NULL, -1);
send_send_data_progressive(session, len, len, dialog);
+
return 0;
}
diff --git a/src/sigstatus.c b/src/sigstatus.c
index 5d4cafa1..d4d23723 100644
--- a/src/sigstatus.c
+++ b/src/sigstatus.c
@@ -161,10 +161,14 @@ static gint timeout_cb(gpointer data)
{
GpgmegtkSigStatus hd = data;
+ gdk_threads_enter();
+
hd->running = 0;
hd->timeout_id_valid = 0;
do_destroy(hd);
+ gdk_threads_leave();
+
return FALSE;
}
diff --git a/src/trayicon.c b/src/trayicon.c
index b142916e..9416141f 100644
--- a/src/trayicon.c
+++ b/src/trayicon.c
@@ -203,8 +203,11 @@ static guint notify_tag = 0;
gboolean notify_timeout_cb(gpointer data)
{
+ gdk_threads_enter();
gtk_status_icon_set_blinking(trayicon.status_icon, FALSE);
notify_tag = 0;
+ gdk_threads_leave();
+
return FALSE;
}