From 71f191b2a609e291a3afcf726ab8aacab572637b Mon Sep 17 00:00:00 2001 From: hiro Date: Thu, 17 Sep 2009 07:26:17 +0000 Subject: introduced multi-threading. git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@2255 ee746299-78ed-0310-b773-934348b2243d --- libsylph/filter.c | 2 +- libsylph/session.c | 12 ++++++--- libsylph/socket.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ libsylph/socket.h | 3 +++ libsylph/utils.c | 56 +++++++++++++++++++++++++++++++++++++++ libsylph/utils.h | 3 +++ 6 files changed, 150 insertions(+), 4 deletions(-) (limited to 'libsylph') 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); -- cgit v1.2.3