From bb18195c269739ad3b48f26945bd46982341b396 Mon Sep 17 00:00:00 2001 From: bertrand Date: Mon, 20 Sep 1999 12:40:39 +0000 Subject: completed 1999-09-20 bertrand * camel/camel-folder-pt-proxy.c (_op_exec_or_plan_for_exec): completed Binch of new funcs: (_maybe_run_next_op): Called by the watch notification when a threaded op is completed (_thread_notification_catch): notification watch call back (_init_notify_system): set up the notification channel (notify_availability): called by threads before completion. svn path=/trunk/; revision=1242 --- camel/camel-folder-pt-proxy.c | 165 +++++++++++++++++++++++++++++++++--------- 1 file changed, 129 insertions(+), 36 deletions(-) (limited to 'camel/camel-folder-pt-proxy.c') diff --git a/camel/camel-folder-pt-proxy.c b/camel/camel-folder-pt-proxy.c index e293e07d64..cf630dd36c 100644 --- a/camel/camel-folder-pt-proxy.c +++ b/camel/camel-folder-pt-proxy.c @@ -21,23 +21,6 @@ * USA */ -/* FIXME : - * - * the current implementation lauches requests - * on the real folder without bothering on wether - * the global mutex (folder->mutex) is locked or - * not. - * This means that you could have 100 threads - * waiting for the mutex at the same time. - * This is not really a bug, more a nasty feature ;) - * - * This will be solved when the CORBA proxy is - * written, as we will need to queue the requests - * on the client side. The same queue mechanism - * will be used for the pthread proxy - * - */ - #include @@ -183,7 +166,18 @@ _finalize (GtkObject *object) } +/* generic operation handling */ + +/** + * _op_exec_or_plan_for_exec: + * @proxy_folder: + * @op: + * + * if no thread is currently running, executes + * op, otherwise push the operation in the operation + * queue. + **/ static void _op_exec_or_plan_for_exec (CamelFolderPtProxy *proxy_folder, CamelOp *op) { @@ -204,6 +198,116 @@ _op_exec_or_plan_for_exec (CamelFolderPtProxy *proxy_folder, CamelOp *op) +/** + * _maybe_run_next_op: run next operation in queue, if any + * @proxy_folder: + * + * + **/ +static void +_maybe_run_next_op (CamelFolderPtProxy *proxy_folder) +{ + CamelOp *op; + CamelOpQueue *op_queue; + pthread_t thread; + + op_queue = proxy_folder->op_queue; + /* get the next pending operation */ + op = camel_op_queue_pop_op (op_queue); + if (!op) { + camel_op_queue_set_service_availability (op_queue, TRUE); + return; + } + + pthread_create (&thread, NULL , (thread_call_func)(op->func), op->param); + camel_op_free (op); +} + + +/** + * _thread_notification_catch: call by glib loop when data is available on the thread io channel + * @source: + * @condition: + * @data: + * + * called by watch set on the IO channel + * + * Return value: + **/ +static gboolean +_thread_notification_catch (GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + CamelFolderPtProxy *proxy_folder = (CamelFolderPtProxy *)data; + gchar op_name; + guint bytes_read; + GIOError error; + + error = g_io_channel_read (source, + &op_name, + 1, + &bytes_read); + if (op_name == 'a') + _maybe_run_next_op (proxy_folder); + + /* do not remove the io watch */ + return TRUE; +} + + + +/** + * _init_notify_system: set the notify channel up + * @proxy_folder: + * + * called once to set the notification channel + **/ +static void +_init_notify_system (CamelFolderPtProxy *proxy_folder) +{ + int filedes[2]; + + /* set up the notification channel */ + if (!pipe (filedes)) { + CAMEL_LOG_WARNING ("could not create pipe in for camel_folder_proxy_init"); + CAMEL_LOG_FULL_DEBUG ("Full error message : %s\n", strerror(errno)); + return; + } + + proxy_folder->pipe_client_fd = filedes [0]; + proxy_folder->pipe_server_fd = filedes [1]; + proxy_folder->notify_source = g_io_channel_unix_new (filedes [0]); + + g_io_add_watch (proxy_folder->notify_source, G_IO_IN, _thread_notification_catch, proxy_folder); + +} + +/** + * notify_availability: notify thread completion + * @proxy_folder: + * + * called by child thread before completion + **/ +static void +notify_availability(CamelFolderPtProxy *proxy_folder) +{ + GIOChannel *notification_channel; + gchar op_name = 'a'; + guint bytes_written; + + notification_channel = proxy_folder->notify_source; + do { + g_io_channel_write (notification_channel, + &op_name, + 1, + &bytes_written); + } while (bytes_written == 1); + +} + + + /* folder->init_with_store implementation */ typedef struct { @@ -212,9 +316,10 @@ typedef struct { } _InitStoreParam; static void -_async_init_with_store (_InitStoreParam *param) +_async_init_with_store (gpointer param) { - CamelFolder *folder = param->folder; + _InitStoreParam *init_store_param = (_InitStoreParam *)param; + CamelFolder *folder = init_store_param->folder; CamelFolderPtProxy *proxy_folder; CamelFolder *real_folder; @@ -224,11 +329,11 @@ _async_init_with_store (_InitStoreParam *param) /* we may block here but we are actually in a * separate thread, so no problem */ - g_static_mutex_lock (&(proxy_folder->mutex)); + /* g_static_mutex_lock (&(proxy_folder->mutex)); */ - CF_CLASS (real_folder)->init_with_store (real_folder, param->parent_store); + CF_CLASS (real_folder)->init_with_store (real_folder, init_store_param->parent_store); g_free (param); - g_static_mutex_unlock (&(proxy_folder->mutex)); + /* g_static_mutex_unlock (&(proxy_folder->mutex)); */ } @@ -237,25 +342,13 @@ _init_with_store (CamelFolder *folder, CamelStore *parent_store) { CamelFolderPtProxy *proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); _InitStoreParam *param; - pthread_t init_store_thread; - int filedes[2]; CamelOp *op; #warning Notify io_channel initialization should be elsewhere /* it can not be in camel_folder_proxy_init * because of the pipe error handling */ - - /* set up the notification channel */ - if (!pipe (filedes)) { - CAMEL_LOG_WARNING ("could not create pipe in for camel_folder_proxy_init"); - CAMEL_LOG_FULL_DEBUG ("Full error message : %s\n", strerror(errno)); - return; - } + _init_notify_system (proxy_folder); - proxy_folder->pipe_client_fd = filedes [0]; - proxy_folder->pipe_server_fd = filedes [1]; - proxy_folder->notify_source = g_io_channel_unix_new (filedes [0]); - op = camel_op_new (); /* param will be freed in _async_init_with_store */ param = g_new (_InitStoreParam, 1); @@ -265,7 +358,7 @@ _init_with_store (CamelFolder *folder, CamelStore *parent_store) op->func = _async_init_with_store; op->param = param; - + _op_exec_or_plan_for_exec (proxy_folder, op); } -- cgit v1.2.3