From bf9f54f9615c1b7b5c8ce5c434d0f78a99f5845b Mon Sep 17 00:00:00 2001 From: bertrand Date: Wed, 13 Oct 1999 21:16:55 +0000 Subject: A lot of changes. The thread proxy mechanism is now functional. The signal proxy needs to be tested though. The thread proxy folder is being implemented. A rough summary : 1999-10-13 bertrand * camel/camel-folder.c (camel_folder_close): the folder->close method is now asynchronous. * camel/camel-folder-pt-proxy.c (_folder_open_cb): (_open): (_folder_open_cb): (_open): open/close method implemented in the thread proxy folder. More to come. * camel/camel-exception.c (camel_exception_xfer): new utility func. * camel/camel-marshal-utils.c: some new marshallers * camel/camel-folder-pt-proxy.c: Some explanations on the thread proxy system. 1999-10-11 bertrand * camel/camel-marshal-utils.c: camel/camel-marshal-utils.h: Handles operation marshalling. * camel/camel-thread-proxy.c: camel/camel-thread-proxy.h: new files. Generic proxy system. * camel/camel-folder-pt-proxy.c moved all proxy related code in dedicated files. (camel_folder_pt_proxy_init): removed proxy initialisation code (_finalize): removed proxy finalization code * camel/camel-exception.c (camel_exception_new): (camel_exception_set): (camel_exception_free): New funcs. svn path=/trunk/; revision=1328 --- camel/Makefile.am | 6 +- camel/camel-exception.c | 46 +++ camel/camel-exception.h | 10 +- camel/camel-folder-pt-proxy.c | 650 ++++++++++++------------------------------ camel/camel-folder-pt-proxy.h | 54 ++-- camel/camel-folder.c | 68 +++-- camel/camel-folder.h | 17 +- camel/camel-marshal-utils.c | 78 +++++ camel/camel-marshal-utils.h | 6 + camel/camel-op-queue.c | 35 ++- camel/camel-op-queue.h | 1 + camel/camel.c | 9 +- camel/camel.h | 1 + 13 files changed, 454 insertions(+), 527 deletions(-) (limited to 'camel') diff --git a/camel/Makefile.am b/camel/Makefile.am index 474718ddf5..b9316d1fca 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -15,10 +15,12 @@ INCLUDES = -I.. -I$(srcdir)/.. -I$(includedir) \ if HAVE_PTHREAD pthread_SRC = \ - camel-folder-pt-proxy.c + camel-folder-pt-proxy.c \ + camel-thread-proxy.c pthread_HDR = \ - camel-folder-pt-proxy.h + camel-folder-pt-proxy.h \ + camel-thread-proxy.h else diff --git a/camel/camel-exception.c b/camel/camel-exception.c index 47261945d5..8b8c70fa10 100644 --- a/camel/camel-exception.c +++ b/camel/camel-exception.c @@ -24,3 +24,49 @@ #include #include "camel-exception.h" +void +camel_exception_free (CamelException *exception) +{ + if (!exception) return; + + if (exception->desc) + g_free (exception->desc); + + g_free (exception); +} + + +CamelException * +camel_exception_new () +{ + CamelException *ex; + + ex = g_new (CamelException, 1); + return ex; +} + + +void +camel_exception_set (CamelException *ex, + ExceptionId id, + const char *desc) +{ + ex->id = id; + if (ex->desc) + g_free (ex->desc); + ex->desc = g_strdup (desc); +} + +void +camel_exception_xfer (CamelException *ex_dst, + CamelException *ex_src) +{ + if (ex_dst->desc) + g_free (ex_dst->desc); + + ex_dst->id = ex_src->id; + ex_dst->desc = ex_src->desc; + + ex_src->desc = NULL; + ex_src->id = CAMEL_EXCEPTION_NONE; +} diff --git a/camel/camel-exception.h b/camel/camel-exception.h index 217d6ca97e..1213511f4d 100644 --- a/camel/camel-exception.h +++ b/camel/camel-exception.h @@ -32,6 +32,8 @@ extern "C" { #pragma } #endif /* __cplusplus }*/ +#include + typedef enum { #include "camel-exception-list.def" @@ -45,7 +47,13 @@ typedef struct { } CamelException; - +void camel_exception_free (CamelException *exception); +CamelException *camel_exception_new (); +void camel_exception_set (CamelException *ex, + ExceptionId id, + const char *desc); +void camel_exception_xfer (CamelException *ex_dst, + CamelException *ex_src); diff --git a/camel/camel-folder-pt-proxy.c b/camel/camel-folder-pt-proxy.c index 9c52615971..8b89bbe72f 100644 --- a/camel/camel-folder-pt-proxy.c +++ b/camel/camel-folder-pt-proxy.c @@ -27,15 +27,12 @@ #include "camel-folder-pt-proxy.h" #include "camel-log.h" #include "camel-marshal-utils.h" +#include "camel-exception.h" #include #include #include #include -/* needed for proper casts of async funcs when - * calling pthreads_create - */ -typedef void * (*thread_call_func) (void *); static CamelFolderClass *parent_class=NULL; @@ -53,14 +50,19 @@ enum CamelFolderFunc { static CamelFuncDef _camel_func_def [CAMEL_FOLDER__LAST_FUNC]; - -static void _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex); +static void _init_with_store (CamelFolder *folder, + CamelStore *parent_store, + CamelException *ex); static void _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelFolderAsyncCallback callback, gpointer user_data, CamelException *ex); -static void _close (CamelFolder *folder, gboolean expunge, CamelException *ex); +static void _close (CamelFolder *folder, + gboolean expunge, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex); static void _set_name (CamelFolder *folder, const gchar *name, CamelException *ex); static const gchar *_get_name (CamelFolder *folder, CamelException *ex); static const gchar *_get_full_name (CamelFolder *folder, CamelException *ex); @@ -87,17 +89,8 @@ static const gchar *_get_message_uid (CamelFolder *folder, CamelMimeMessage *mes static CamelMimeMessage *_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex); static GList *_get_uid_list (CamelFolder *folder, CamelException *ex); - static void _finalize (GtkObject *object); -/* for the proxy watch */ -static gboolean _thread_notification_catch (GIOChannel *source, - GIOCondition condition, - gpointer data); -static void _notify_availability (CamelFolder *folder, gchar op_name); -static void _init_notify_system (CamelFolderPtProxy *proxy_folder); -static void _init_signals_proxy (CamelFolderPtProxy *proxy_folder); - static void camel_folder_pt_proxy_class_init (CamelFolderPtProxyClass *camel_folder_pt_proxy_class) @@ -115,7 +108,7 @@ camel_folder_pt_proxy_class_init (CamelFolderPtProxyClass *camel_folder_pt_proxy camel_folder_class->set_name = _set_name; camel_folder_class->get_name = _get_name; camel_folder_class->can_hold_folders = _can_hold_folders; - camel_folder_class->can_hold_messages = _can_hold_messages; + camel_folder_class->can_hold_messages = _can_hold_messages; camel_folder_class->exists = _exists; camel_folder_class->is_open = _is_open; camel_folder_class->get_folder = _get_folder; @@ -142,8 +135,32 @@ camel_folder_pt_proxy_class_init (CamelFolderPtProxyClass *camel_folder_pt_proxy /* function definition for proxying */ proxy_class->open_func_def = camel_func_def_new (camel_marshal_NONE__POINTER_INT_POINTER_POINTER, - 1, - GTK_TYPE_INT); + 4, + GTK_TYPE_POINTER, + GTK_TYPE_INT, + GTK_TYPE_POINTER, + GTK_TYPE_POINTER); + proxy_class->open_cb_def = + camel_func_def_new (camel_marshal_NONE__POINTER_POINTER_POINTER, + 3, + GTK_TYPE_POINTER, + GTK_TYPE_POINTER, + GTK_TYPE_POINTER); + + proxy_class->close_func_def = + camel_func_def_new (camel_marshal_NONE__POINTER_BOOL_POINTER_POINTER, + 4, + GTK_TYPE_POINTER, + GTK_TYPE_BOOL, + GTK_TYPE_POINTER, + GTK_TYPE_POINTER); + proxy_class->close_cb_def = + camel_func_def_new (camel_marshal_NONE__POINTER_POINTER_POINTER, + 3, + GTK_TYPE_POINTER, + GTK_TYPE_POINTER, + GTK_TYPE_POINTER); + } @@ -152,11 +169,8 @@ camel_folder_pt_proxy_class_init (CamelFolderPtProxyClass *camel_folder_pt_proxy static void camel_folder_pt_proxy_init (CamelFolderPtProxy *folder_pt_proxy) { - folder_pt_proxy->op_queue = camel_op_queue_new (); - folder_pt_proxy->signal_data_cond = g_cond_new(); - folder_pt_proxy->signal_data_mutex = g_mutex_new(); - _init_signals_proxy (folder_pt_proxy); - _init_notify_system (folder_pt_proxy); + folder_pt_proxy->thread_ex = camel_exception_new (); + folder_pt_proxy->pud = g_new (_ProxyCbUserData, 1); } @@ -195,8 +209,9 @@ _finalize (GtkObject *object) GList *message_node; CAMEL_LOG_FULL_DEBUG ("Entering CamelFolderPtProxy::finalize\n"); - g_cond_free (camel_folder_pt_proxy->signal_data_cond); - g_mutex_free (camel_folder_pt_proxy->signal_data_mutex); + + camel_exception_free (camel_folder_pt_proxy->thread_ex); + g_free (camel_folder_pt_proxy->pud); GTK_OBJECT_CLASS (parent_class)->finalize (object); CAMEL_LOG_FULL_DEBUG ("Leaving CamelFolderPtProxy::finalize\n"); } @@ -205,417 +220,100 @@ _finalize (GtkObject *object) -/* function proxies definitions */ - - -/* generic operation handling */ +/*********/ - -/** - * _op_run_free_notify: - * @folder: folder to notify when the operation is completed. - * @op: operation to run. - * - * run an operation, free the operation field - * and then notify the main thread of the op - * completion. - * - * these routine is entended to be called - * in a thread - * - * Return value: - **/ -void -_op_run_free_and_notify (CamelOp *op) -{ - gboolean error; - CamelFolder *folder; - - camel_op_run (op); - camel_op_free (op); - folder = camel_op_get_user_data (op); - _notify_availability (folder, 'a'); -} - - - - -/** - * _run_next_op_in_thread: - * @proxy_folder: - * - * run the next operation pending in the proxy - * operation queue - **/ -static void -_run_next_op_in_thread (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; - } - - /* run the operation in a child thread */ - pthread_create (&thread, NULL, (thread_call_func) _op_run_free_and_notify, op); - -} +/**** Operations implementation ****/ -/** - * _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) +static gpointer +_proxy_cb_user_data (_ProxyCbUserData *pud, + CamelFolderAsyncCallback real_callback, + CamelFolderPtProxy *proxy_folder, + CamelException *ex, + gpointer real_user_data) { - CamelOpQueue *op_queue; - pthread_t thread; - - op_queue = proxy_folder->op_queue; - - /* put the real folder in the user data - so that it can be notified when the - operation is completed */ - camel_op_set_user_data (op, proxy_folder->real_folder); - - /* get next operation */ - camel_op_queue_push_op (op_queue, op); - - if (camel_op_queue_get_service_availability (op_queue)) { - /* no thread is currently running, run - * the next operation. */ - camel_op_queue_set_service_availability (op_queue, FALSE); - /* when the operation is completed in the - child thread the main thread gets - notified and executes next operation - (see _thread_notification_catch, case 'a') - so there is no need to set the service - availability to FALSE except here - */ - _run_next_op_in_thread (proxy_folder); - } + pud->real_callback = real_callback; + pud->proxy_folder = proxy_folder; + pud->ex = ex; + pud->real_user_data = real_user_data; + return (gpointer)pud; } +/* ******** */ - - - - -/** - * _init_notify_system: set the notify channel up - * @proxy_folder: - * - * called once to set the notification channel - **/ +/* thread->init_with_store implementation */ static void -_init_notify_system (CamelFolderPtProxy *proxy_folder) +_init_with_store (CamelFolder *folder, + CamelStore *parent_store, + CamelException *ex) { - 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)); + parent_class->init_with_store (folder, parent_store, ex); + if (ex->id != CAMEL_EXCEPTION_NONE) 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]); - - /* the _thread_notification_catch function - * will be called in the main thread when the - * child thread writes some data in the channel */ - g_io_add_watch (proxy_folder->notify_source, G_IO_IN, - _thread_notification_catch, - proxy_folder); - -} - -/** - * notify_availability: notify thread completion - * @folder: real folder (in the child thread) - * @op_name: operation name - * - * called by child thread (real folder) to notify the main - * thread (folder proxy) something is available for him. - * What this thing is depends on @op_name: - * - * 'a' : thread available. That means the thread is ready - * to process an operation. - * 's' : a signal is available. Used by the signal proxy. - * - */ -static void -_notify_availability (CamelFolder *folder, gchar op_name) -{ - GIOChannel *notification_channel; - CamelFolderPtProxy *proxy_folder; - guint bytes_written; - - proxy_folder = (CamelFolderPtProxy *)gtk_object_get_data (GTK_OBJECT (folder), - "proxy_folder"); - notification_channel = proxy_folder->notify_source; - do { - /* the write operation will trigger the - * watch on the main thread side */ - g_io_channel_write (notification_channel, - &op_name, - 1, - &bytes_written); - } while (bytes_written == 1); - -} - - - -/* signal proxying */ - -static void -_signal_marshaller_server_side (GtkObject *object, - gpointer data, - guint n_args, - GtkArg *args) -{ - CamelFolder *folder; - CamelFolderPtProxy *proxy_folder; - guint signal_id; - - folder = CAMEL_FOLDER (object); - proxy_folder = CAMEL_FOLDER_PT_PROXY (gtk_object_get_data (object, "proxy_folder")); - signal_id = (guint)data; - g_assert (proxy_folder); - - g_mutex_lock (proxy_folder->signal_data_mutex); - - /* we are going to wait for the main client thread - * to have emitted the last signal we asked him - * to proxy. - */ - while (proxy_folder->signal_data.args) - g_cond_wait (proxy_folder->signal_data_cond, - proxy_folder->signal_data_mutex); - - proxy_folder->signal_data.signal_id = signal_id; - proxy_folder->signal_data.args = args; - - - g_mutex_unlock (proxy_folder->signal_data_mutex); - - /* tell the main thread there is a signal pending */ - _notify_availability (folder, 's'); +#warning use proxy store here + CF_CLASS (folder)->init_with_store (CAMEL_FOLDER_PT_PROXY (folder)->real_folder, + parent_store, + ex); } -static void -_signal_marshaller_client_side (CamelFolderPtProxy *proxy_folder) -{ - g_mutex_lock (proxy_folder->signal_data_mutex); - g_assert (proxy_folder->signal_data.args); - - /* emit the pending signal */ - gtk_signal_emitv (GTK_OBJECT (proxy_folder), - proxy_folder->signal_data.signal_id, - proxy_folder->signal_data.args); - - proxy_folder->signal_data.args = NULL; - - /* if waiting for the signal to be treated, - * awake the client thread up - */ - g_cond_signal (proxy_folder->signal_data_cond); - g_mutex_unlock (proxy_folder->signal_data_mutex); -} - -static void -_init_signals_proxy (CamelFolderPtProxy *proxy_folder) -{ - CamelFolder *real_folder; - GtkType camel_folder_type; - guint i; - char *signal_to_proxy[] = { - NULL - }; - - camel_folder_type = CAMEL_FOLDER_TYPE; - real_folder = proxy_folder->real_folder; - - for (i=0; signal_to_proxy[i]; i++) { - /* connect the signal to the signal marshaller - * user_data is the signal id */ - gtk_signal_connect_full (GTK_OBJECT (real_folder), - signal_to_proxy[i], - NULL, - _signal_marshaller_server_side, - (gpointer)gtk_signal_lookup (signal_to_proxy[i], camel_folder_type), - NULL, - TRUE, - FALSE); - } - - - - -} - -/**** catch notification from child thread ****/ -/** - * _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 +/* a little bit of explanation for the folder_class->open + * method implementation : * - * Return value: TRUE because we don't want the watch to be removed - **/ -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); - - switch (op_name) { - case 'a': /* the thread is OK for a new operation */ - _run_next_op_in_thread (proxy_folder); - break; - case 's': /* there is a pending signal to proxy */ - _signal_marshaller_client_side (proxy_folder); - break; - } - - /* do not remove the io watch */ - return TRUE; -} - - - - - -/*********/ + * the proxy object "open" method is called by the client + * program in the main thread. This method creates a + * CamelOp object containing all the necessary informations + * to call the corresponding "open" method on the real + * folder object in the child folder. This CamelOp object + * is pushed in a queue in the main thread (see the + * CamelThreadProxy structure for more details). + * The operations in this queue are executed one by one + * in a child thread. + * Once the "open" method of the real object is finished, + * it calls a callback. This callback is not the one supplied + * by the client object. Instead, the _folder_open_cb() + * function is called (in the child thread) which pushes + * the real callback function in another operation queue. + * The real callback is then called in the main thread. + */ -/**** Operations implementation ****/ +/* folder->open implementation */ /* - * the _async prefixed operations are - * executed in a child thread. - * When completed, they must call - * notify_availability () in order to - * tell the main thread it can process - * a new operation. - * + * proxy callback. Called in the child thread by the + * real folder "open" method when it is completed */ - -/* folder->init_with_store implementation */ static void -_init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex) -{ - CamelFolderPtProxy *proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); - -#warning Notify io_channel initialization should be elsewhere - /* it can not be in camel_folder_proxy_init - * because of the pipe error handling */ - _init_notify_system (proxy_folder); - gtk_object_set_data (GTK_OBJECT (proxy_folder->real_folder), - "proxy_folder", - proxy_folder); - - CF_CLASS (proxy_folder)->init_with_store (proxy_folder->real_folder, - parent_store, - ex); -} - - - -/* folder->open implementation */ - -typedef struct { - CamelFolder *folder; - CamelFolderOpenMode mode; - CamelFolderAsyncCallback callback; - gpointer user_data; - CamelException *ex; -} _OpenFolderParam; - - -void _folder_open_cb (CamelFolder *folder, gpointer user_data, CamelException *ex) { - CamelFolderPtProxy *proxy_folder; - CamelFolderAsyncCallback callback; - _OpenFolderParam *param; - CamelOp *op; - - - + CamelOp *cb; + _ProxyCbUserData *pud; + CamelFuncDef *cb_def; - proxy_folder = gtk_object_get_data (GTK_OBJECT (folder), - "proxy_folder"); - callback = (CamelFolderAsyncCallback)user_data; - - g_assert (proxy_folder); - g_assert (callback); - //op = camel_op_new (); - - //param = g_new (_OpenFolderParam, 1); - //param->folder = proxy_folder; - //param->user_data = user_data; - - -} + /* transfer the exception information from "ex" to the + * client supplied exception (kept in pud->ex) */ + camel_exception_xfer (pud->ex, ex); -static void -_async_open (gpointer param) -{ - _OpenFolderParam *open_folder_param; - CamelFolder *folder; - CamelException *ex; - - open_folder_param = (_OpenFolderParam *)param; - - folder = open_folder_param->folder; - - CF_CLASS (folder)->open (folder, - open_folder_param->mode, - open_folder_param->callback, - open_folder_param->user_data, - NULL); - g_free (param); - _notify_availability (folder, 'a'); + /* create an operation which will call the real client + * supplied callback in the main thread */ + cb_def = CAMEL_FOLDER_PT_PROXY_CLASS(pud->proxy_folder)->open_cb_def; + cb = camel_marshal_create_op (cb_def, + pud->real_callback, + pud->proxy_folder, + pud->real_user_data, + pud->ex); + camel_thread_proxy_push_cb (pud->proxy_folder->proxy_object, cb); } - static void _open (CamelFolder *folder, CamelFolderOpenMode mode, @@ -623,23 +321,39 @@ _open (CamelFolder *folder, gpointer user_data, CamelException *ex) { - CamelFolderPtProxy *proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); - _OpenFolderParam *param; + CamelFolderPtProxy *proxy_folder; CamelOp *op; - - //op = camel_op_new (); - - //param = g_new (_OpenFolderParam, 1); - //param->folder = proxy_folder->real_folder; - //param->mode = mode; - //param->callback = callback; - //param->user_data = user_data; - - - //op->func = _async_open; - //op->param = param; - - //_op_exec_or_plan_for_exec (proxy_folder, op); + CamelFuncDef *func_def; + + proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); + + /* create an operation corresponding to the "open" + * method of the real object. The operation definition + * is common to all instances of the CamelFolderPtProxy + * class so it is contained in the CamelFolderPtProxyClass + * structure. */ + func_def = CAMEL_FOLDER_PT_PROXY_CLASS(proxy_folder)->open_func_def; + if (callback) + op = camel_marshal_create_op (func_def, + CAMEL_FOLDER_CLASS (proxy_folder->real_folder)->open, + proxy_folder->real_folder, + mode, + _folder_open_cb, + _proxy_cb_user_data (proxy_folder->pud, callback, proxy_folder, ex, user_data), + proxy_folder->thread_ex); + else + op = camel_marshal_create_op (func_def, + CAMEL_FOLDER_CLASS (proxy_folder->real_folder)->open, + proxy_folder->real_folder, + mode, + NULL, + NULL, + NULL); + /* push the operation in the operation queue. This operation + * will be executed in a child thread but only one operation + * will be executed at a time, so that folder implementations + * don't have to be MultiThread safe. */ + camel_thread_proxy_push_op (proxy_folder->proxy_object, op); } @@ -647,84 +361,82 @@ _open (CamelFolder *folder, /* folder->close implementation */ -typedef struct { - CamelFolder *folder; - gboolean expunge; - CamelException *ex; -} _CloseFolderParam; -static void -_async_close (gpointer param) +static void +_folder_close_cb (CamelFolder *folder, + gpointer user_data, + CamelException *ex) { - _CloseFolderParam *close_folder_param; - CamelFolder *folder; - CamelException *ex; + CamelOp *cb; + _ProxyCbUserData *pud; + CamelFuncDef *cb_def; - close_folder_param = (_CloseFolderParam *)param; - - folder = close_folder_param->folder; - - CF_CLASS (folder)->close (folder, - close_folder_param->expunge, - NULL); - g_free (param); - _notify_availability (folder, 'a'); + camel_exception_xfer (pud->ex, ex); + cb_def = CAMEL_FOLDER_PT_PROXY_CLASS(pud->proxy_folder)->close_cb_def; + cb = camel_marshal_create_op (cb_def, + pud->real_callback, + pud->proxy_folder, + pud->real_user_data, + pud->ex); + camel_thread_proxy_push_cb (pud->proxy_folder->proxy_object, cb); } static void -_close (CamelFolder *folder, gboolean expunge, CamelException *ex) +_close (CamelFolder *folder, + gboolean expunge, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex) { - CamelFolderPtProxy *proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); - _CloseFolderParam *param; + CamelFolderPtProxy *proxy_folder; CamelOp *op; + CamelFuncDef *func_def; - //op = camel_op_new (); - - //param = g_new (_CloseFolderParam, 1); - //param->folder = proxy_folder->real_folder; - //param->expunge = expunge; + proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); - //op->func = _async_close; - //op->param = param; - - //_op_exec_or_plan_for_exec (proxy_folder, op); + func_def = CAMEL_FOLDER_PT_PROXY_CLASS(proxy_folder)->close_func_def; + if (callback) + op = camel_marshal_create_op (func_def, + CAMEL_FOLDER_CLASS (proxy_folder->real_folder)->open, + proxy_folder->real_folder, + expunge, + _folder_close_cb, + _proxy_cb_user_data (proxy_folder->pud, callback, proxy_folder, ex, user_data), + proxy_folder->thread_ex); + else + op = camel_marshal_create_op (func_def, + CAMEL_FOLDER_CLASS (proxy_folder->real_folder)->open, + proxy_folder->real_folder, + expunge, + NULL, + NULL, + NULL); + camel_thread_proxy_push_op (proxy_folder->proxy_object, op); + } -/* folder->set_name implementation */ - -typedef struct { - CamelFolder *folder; - const gchar *name; - CamelException *ex; -} _SetNameFolderParam; +/* folder->set_name implementation */ static void _async_set_name (gpointer param) { - _SetNameFolderParam *set_name_folder_param; CamelFolder *folder; CamelException *ex; - set_name_folder_param = (_SetNameFolderParam *)param; - folder = set_name_folder_param->folder; + //CF_CLASS (folder)->set_name (folder, + // set_name_folder_param->name, + // NULL); - CF_CLASS (folder)->set_name (folder, - set_name_folder_param->name, - NULL); - g_free (param); - _notify_availability (folder, 'a'); - } static void _set_name (CamelFolder *folder, const gchar *name, CamelException *ex) { CamelFolderPtProxy *proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); - _SetNameFolderParam *param; CamelOp *op; //op = camel_op_new (); @@ -747,8 +459,8 @@ _get_name (CamelFolder *folder, CamelException *ex) { CamelFolderPtProxy *proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); - return CF_CLASS (proxy_folder->real_folder)-> - get_name (proxy_folder->real_folder, ex); + //return CF_CLASS (proxy_folder->real_folder)-> + //get_name (proxy_folder->real_folder, ex); } diff --git a/camel/camel-folder-pt-proxy.h b/camel/camel-folder-pt-proxy.h index e540c78d4b..285306af71 100644 --- a/camel/camel-folder-pt-proxy.h +++ b/camel/camel-folder-pt-proxy.h @@ -28,8 +28,15 @@ #ifndef CAMEL_FOLDER_PT_PROXY_H #define CAMEL_FOLDER_PT_PROXY_H 1 + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + #include "camel-folder.h" #include "camel-op-queue.h" +#include "camel-thread-proxy.h" #define CAMEL_FOLDER_PT_PROXY_TYPE (camel_folder_pt_proxy_get_type ()) @@ -37,47 +44,42 @@ #define CAMEL_FOLDER_PT_PROXY_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_FOLDER_PT_PROXY_TYPE, CamelFolderPtProxyClass)) #define IS_CAMEL_FOLDER_PT_PROXY(o) (GTK_CHECK_TYPE((o), CAMEL_FOLDER_PT_PROXY_TYPE)) -typedef struct { - guint signal_id; - GtkArg *args; -} PtProxySignaData; - - +typedef struct _CamelFolderPtProxy CamelFolderPtProxy; typedef struct { + CamelFolderAsyncCallback real_callback; + CamelFolderPtProxy *proxy_folder; + CamelException *ex; + gpointer real_user_data; +} _ProxyCbUserData; + +struct _CamelFolderPtProxy { CamelFolder parent; - gchar *real_url; + /* private fields */ CamelFolder *real_folder; - - CamelOpQueue *op_queue; - gint pipe_client_fd; - gint pipe_server_fd; - GIOChannel *notify_source; - - /* used for signal proxy */ - GMutex *signal_data_mutex; - GCond *signal_data_cond; - PtProxySignaData signal_data; -} CamelFolderPtProxy; + CamelThreadProxy *proxy_object; + CamelException *thread_ex; + _ProxyCbUserData *pud; + +}; typedef struct { CamelFolderClass parent_class; + /* functions and callbacks definition (for marshalling) */ CamelFuncDef *open_func_def; + CamelFuncDef *open_cb_def; + CamelFuncDef *close_func_def; + CamelFuncDef *close_cb_def; } CamelFolderPtProxyClass; -/* some marshallers */ -void camel_marshal_NONE__POINTER_INT (CamelFunc func, - GtkArg *args); - -void camel_marshal_NONE__POINTER_INT_POINTER (CamelFunc func, - GtkArg *args); - - +#ifdef __cplusplus +} +#endif /* __cplusplus */ #endif /* CAMEL_FOLDER_PT_PROXY_H */ diff --git a/camel/camel-folder.c b/camel/camel-folder.c index f887d83ad0..ef37bb8c7b 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -36,7 +36,11 @@ static void _open (CamelFolder *folder, CamelFolderAsyncCallback callback, gpointer user_data, CamelException *ex); -static void _close (CamelFolder *folder, gboolean expunge, CamelException *ex); +static void _close (CamelFolder *folder, + gboolean expunge, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex); static void _set_name (CamelFolder *folder, const gchar *name, CamelException *ex); /* static void _set_full_name (CamelFolder *folder, const gchar *name); */ static const gchar *_get_name (CamelFolder *folder, CamelException *ex); @@ -189,13 +193,7 @@ _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException -/** - * _open: Open a folder - * @folder: The folder object - * @mode: open mode (R/W/RW ?) - * - * - **/ + static void _open (CamelFolder *folder, CamelFolderOpenMode mode, @@ -207,7 +205,19 @@ _open (CamelFolder *folder, /* folder->open_mode = mode; */ } - +/** + * camel_folder_open: Open a folder + * @folder: The folder object + * @mode: open mode (R/W/RW ?) + * @callback: function to call when the operation is over + * @user_data: data to pass to the callback + * @ex: exception object + * + * Open a folder in a given mode. When the opration is over + * the callback is called and the client program can determine + * if the operation suceeded by examining the exception. + * + **/ void camel_folder_open (CamelFolder *folder, CamelFolderOpenMode mode, @@ -220,25 +230,39 @@ camel_folder_open (CamelFolder *folder, -/** - * _close:Close a folder. - * @folder: - * @expunge: if TRUE, the flagged message are deleted. - * - * Put a folder in its closed state, and possibly - * expunge the flagged messages. - **/ + static void -_close (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - if (expunge) camel_folder_expunge (folder, FALSE, ex); +_close (CamelFolder *folder, + gboolean expunge, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex) +{ folder->open_state = FOLDER_CLOSE; } +/** + * camel_folder_close: Close a folder. + * @folder: The folder object + * @expunge: if TRUE, the flagged message are deleted. + * @callback: function to call when the operation is over + * @user_data: data to pass to the callback + * @ex: exception object + * + * Put a folder in its closed state, and possibly + * expunge the flagged messages. The callback is called + * when the operation is over and the client program can determine + * if the operation suceeded by examining the exception. + * + **/ void -camel_folder_close (CamelFolder *folder, gboolean expunge, CamelException *ex) +camel_folder_close (CamelFolder *folder, + gboolean expunge, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex) { - CF_CLASS(folder)->close (folder, expunge, ex); + CF_CLASS(folder)->close (folder, expunge, callback, user_data, ex); } diff --git a/camel/camel-folder.h b/camel/camel-folder.h index 7f454d92e5..5ab39f8ed8 100644 --- a/camel/camel-folder.h +++ b/camel/camel-folder.h @@ -88,13 +88,19 @@ typedef struct { GtkObjectClass parent_class; /* Virtual methods */ - void (*init_with_store) (CamelFolder *folder, CamelStore *parent_store, CamelException *ex); + void (*init_with_store) (CamelFolder *folder, + CamelStore *parent_store, + CamelException *ex); void (*open) (CamelFolder *folder, CamelFolderOpenMode mode, CamelFolderAsyncCallback callback, gpointer user_data, CamelException *ex); - void (*close) (CamelFolder *folder, gboolean expunge, CamelException *ex); + void (*close) (CamelFolder *folder, + gboolean expunge, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex); void (*set_name) (CamelFolder *folder, const gchar *name, CamelException *ex); /* void (*set_full_name) (CamelFolder *folder, const gchar *name); */ const gchar * (*get_name) (CamelFolder *folder, CamelException *ex); @@ -139,7 +145,12 @@ void camel_folder_open (CamelFolder *folder, gpointer user_data, CamelException *ex); -void camel_folder_close (CamelFolder *folder, gboolean expunge, CamelException *ex); +void camel_folder_close (CamelFolder *folder, + gboolean expunge, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex); + gboolean camel_folder_create (CamelFolder *folder, CamelException *ex); gboolean camel_folder_delete (CamelFolder *folder, gboolean recurse, CamelException *ex); gboolean camel_folder_delete_messages (CamelFolder *folder, CamelException *ex); diff --git a/camel/camel-marshal-utils.c b/camel/camel-marshal-utils.c index bb12318837..7ea540224c 100644 --- a/camel/camel-marshal-utils.c +++ b/camel/camel-marshal-utils.c @@ -144,6 +144,7 @@ camel_op_new (CamelFuncDef *func_def) { CamelOp *op; + CAMEL_LOG_FULL_DEBUG ("Entering CamelOp::new\n"); g_static_mutex_lock (&op_chunk_mutex); if (!op_chunk) op_chunk = g_mem_chunk_create (CamelOp, @@ -155,6 +156,7 @@ camel_op_new (CamelFuncDef *func_def) op->func_def = func_def; op->params = g_new (GtkArg, func_def->n_params); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOp::new\n"); return op; } @@ -169,8 +171,10 @@ camel_op_new (CamelFuncDef *func_def) void camel_op_free (CamelOp *op) { + CAMEL_LOG_FULL_DEBUG ("Entering CamelOp::free\n"); g_free (op->params); g_chunk_free (op, op_chunk); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOp::free\n"); } @@ -187,11 +191,13 @@ camel_op_run (CamelOp *op) GtkArg *params; gboolean error; + CAMEL_LOG_FULL_DEBUG ("Entering CamelOp::run\n"); g_assert (op); g_assert (op->func_def); g_assert (op->params); op->func_def->marshal (op->func, op->params); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOp::run\n"); } @@ -207,8 +213,10 @@ camel_op_run (CamelOp *op) void camel_op_set_user_data (CamelOp *op, gpointer user_data) { + CAMEL_LOG_FULL_DEBUG ("Entering CamelOp::set_user_data\n"); g_assert (op); op->user_data = user_data; + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOp::set_user_data\n"); } @@ -224,7 +232,9 @@ camel_op_set_user_data (CamelOp *op, gpointer user_data) gpointer camel_op_get_user_data (CamelOp *op) { + CAMEL_LOG_FULL_DEBUG ("Entering CamelOp::get_user_data\n"); g_assert (op); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOp::get_user_data\n"); return op->user_data; } @@ -239,9 +249,12 @@ void camel_marshal_NONE__POINTER_INT (CamelFunc func, GtkArg *args) { CamelMarshal_NONE__POINTER_INT rfunc; + + CAMEL_LOG_FULL_DEBUG ("Entering camel_marshal_NONE__POINTER_INT\n"); rfunc = (CamelMarshal_NONE__POINTER_INT) func; (* rfunc) (GTK_VALUE_POINTER(args[0]), GTK_VALUE_INT(args[1])); + CAMEL_LOG_FULL_DEBUG ("Leaving camel_marshal_NONE__POINTER_INT\n"); } @@ -255,12 +268,33 @@ void camel_marshal_NONE__POINTER_INT_POINTER (CamelFunc func, GtkArg *args) { CamelMarshal_NONE__POINTER_INT_POINTER rfunc; + + CAMEL_LOG_FULL_DEBUG ("Entering camel_marshal_NONE__POINTER_INT_POINTER\n"); rfunc = (CamelMarshal_NONE__POINTER_INT_POINTER) func; (* rfunc) (GTK_VALUE_POINTER(args[0]), GTK_VALUE_INT(args[1]), GTK_VALUE_POINTER(args[2])); + CAMEL_LOG_FULL_DEBUG ("Leaving camel_marshal_NONE__POINTER_INT_POINTER\n"); } + +typedef void (*CamelMarshal_NONE__POINTER_BOOL_POINTER) (gpointer arg1, + gboolean arg2, + gpointer arg3); +void camel_marshal_NONE__POINTER_BOOL_POINTER (CamelFunc func, + GtkArg *args) +{ + CamelMarshal_NONE__POINTER_BOOL_POINTER rfunc; + + CAMEL_LOG_FULL_DEBUG ("Entering camel_marshal_NONE__POINTER_BOOL_POINTER\n"); + rfunc = (CamelMarshal_NONE__POINTER_BOOL_POINTER) func; + (* rfunc) (GTK_VALUE_POINTER(args[0]), + GTK_VALUE_BOOL(args[1]), + GTK_VALUE_POINTER(args[2])); + CAMEL_LOG_FULL_DEBUG ("Leaving camel_marshal_NONE__POINTER_BOOL_POINTER\n"); +} + + typedef void (*CamelMarshal_NONE__POINTER_INT_POINTER_POINTER) (gpointer arg1, gint arg2, gpointer arg3, @@ -269,11 +303,52 @@ void camel_marshal_NONE__POINTER_INT_POINTER_POINTER (CamelFunc func, GtkArg *args) { CamelMarshal_NONE__POINTER_INT_POINTER_POINTER rfunc; + + CAMEL_LOG_FULL_DEBUG ("Entering camel_marshal_NONE__POINTER_INT_POINTER_POINTER\n"); rfunc = (CamelMarshal_NONE__POINTER_INT_POINTER_POINTER) func; (* rfunc) (GTK_VALUE_POINTER(args[0]), GTK_VALUE_INT(args[1]), GTK_VALUE_POINTER(args[2]), GTK_VALUE_POINTER(args[3])); + CAMEL_LOG_FULL_DEBUG ("Leaving camel_marshal_NONE__POINTER_INT_POINTER_POINTER\n"); +} + + + +typedef void (*CamelMarshal_NONE__POINTER_BOOL_POINTER_POINTER) (gpointer arg1, + gboolean arg2, + gpointer arg3, + gpointer arg4); +void camel_marshal_NONE__POINTER_BOOL_POINTER_POINTER (CamelFunc func, + GtkArg *args) +{ + CamelMarshal_NONE__POINTER_BOOL_POINTER_POINTER rfunc; + + CAMEL_LOG_FULL_DEBUG ("Entering camel_marshal_NONE__POINTER_BOOL_POINTER_POINTER\n"); + rfunc = (CamelMarshal_NONE__POINTER_BOOL_POINTER_POINTER) func; + (* rfunc) (GTK_VALUE_POINTER(args[0]), + GTK_VALUE_BOOL(args[1]), + GTK_VALUE_POINTER(args[2]), + GTK_VALUE_POINTER(args[3])); + CAMEL_LOG_FULL_DEBUG ("Leaving camel_marshal_NONE__POINTER_BOOL_POINTER_POINTER\n"); +} + + + +typedef void (*CamelMarshal_NONE__POINTER_POINTER_POINTER) (gpointer arg1, + gpointer arg2, + gpointer arg3); +void camel_marshal_NONE__POINTER_POINTER_POINTER (CamelFunc func, + GtkArg *args) +{ + CamelMarshal_NONE__POINTER_POINTER_POINTER rfunc; + + CAMEL_LOG_FULL_DEBUG ("Entering camel_marshal_NONE__POINTER_POINTER_POINTER\n"); + rfunc = (CamelMarshal_NONE__POINTER_POINTER_POINTER) func; + (* rfunc) (GTK_VALUE_POINTER(args[0]), + GTK_VALUE_POINTER(args[1]), + GTK_VALUE_POINTER(args[2])); + CAMEL_LOG_FULL_DEBUG ("Leaving camel_marshal_NONE__POINTER_POINTER_POINTER\n"); } @@ -282,8 +357,11 @@ void camel_marshal_NONE__INT (CamelFunc func, GtkArg *args) { CamelMarshal_NONE__INT rfunc; + + CAMEL_LOG_FULL_DEBUG ("Entering camel_marshal_NONE__INT\n"); rfunc = (CamelMarshal_NONE__INT) func; (* rfunc) (GTK_VALUE_INT (args[0])); + CAMEL_LOG_FULL_DEBUG ("Leaving camel_marshal_NONE__INT\n"); } diff --git a/camel/camel-marshal-utils.h b/camel/camel-marshal-utils.h index 324f32e644..da62309d55 100644 --- a/camel/camel-marshal-utils.h +++ b/camel/camel-marshal-utils.h @@ -80,8 +80,14 @@ CamelOp *camel_marshal_create_op (CamelFuncDef *func_def, CamelFunc func, ...); /* marshallers */ void camel_marshal_NONE__POINTER_INT_POINTER (CamelFunc func, GtkArg *args); +void camel_marshal_NONE__POINTER_BOOL_POINTER (CamelFunc func, + GtkArg *args); void camel_marshal_NONE__POINTER_INT_POINTER_POINTER (CamelFunc func, GtkArg *args); +void camel_marshal_NONE__POINTER_BOOL_POINTER_POINTER (CamelFunc func, + GtkArg *args); +void camel_marshal_NONE__POINTER_POINTER_POINTER (CamelFunc func, + GtkArg *args); void camel_marshal_NONE__INT (CamelFunc func, GtkArg *args); diff --git a/camel/camel-op-queue.c b/camel/camel-op-queue.c index a722c16f80..415c607859 100644 --- a/camel/camel-op-queue.c +++ b/camel/camel-op-queue.c @@ -22,7 +22,9 @@ /* MT safe */ - + +#include +#include "camel-log.h" #include "camel-op-queue.h" static GStaticMutex op_queue_mutex = G_STATIC_MUTEX_INIT; @@ -41,14 +43,27 @@ camel_op_queue_new () { CamelOpQueue *op_queue; + CAMEL_LOG_FULL_DEBUG ("Entering CamelOpQueue::new\n"); op_queue = g_new (CamelOpQueue, 1); op_queue->ops_tail = NULL; op_queue->ops_head = NULL; - + op_queue->service_available = TRUE; + + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOpQueue::new\n"); + return op_queue; } +void +camel_op_queue_free (CamelOpQueue *op_queue) +{ + CAMEL_LOG_FULL_DEBUG ("Entering CamelOpQueue::free\n"); + g_list_free (op_queue->ops_head); + g_free (op_queue); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOpQueue::free\n"); +} + /** * camel_op_queue_push_op: Add an operation to the queue * @queue: queue object @@ -62,14 +77,18 @@ camel_op_queue_push_op (CamelOpQueue *queue, CamelOp *op) { GList *new_op; + CAMEL_LOG_FULL_DEBUG ("Entering CamelOpQueue::push_op\n"); g_assert (queue); g_static_mutex_lock (&op_queue_mutex); if (!queue->ops_tail) { + CAMEL_LOG_FULL_DEBUG ("CamelOpQueue::push_op queue does not exists yet. " + "Creating it\n"); queue->ops_head = g_list_prepend (NULL, op); queue->ops_tail = queue->ops_head; } else queue->ops_head = g_list_prepend (queue->ops_head, op); g_static_mutex_unlock (&op_queue_mutex); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOpQueue::push_op\n"); } @@ -87,14 +106,18 @@ camel_op_queue_pop_op (CamelOpQueue *queue) GList *op_list; CamelOp *op; + CAMEL_LOG_FULL_DEBUG ("Entering CamelOpQueue::pop_op\n"); g_assert (queue); g_static_mutex_lock (&op_queue_mutex); op_list = queue->ops_tail; + if (!op_list) return NULL; + queue->ops_tail = queue->ops_tail->prev; op = (CamelOp *)op_list->data; g_static_mutex_unlock (&op_queue_mutex); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOpQueue::pop_op\n"); return op; } @@ -112,11 +135,12 @@ camel_op_queue_run_next_op (CamelOpQueue *queue) { CamelOp *op; + CAMEL_LOG_FULL_DEBUG ("Entering CamelOpQueue::run_next_op\n"); op = camel_op_queue_pop_op (queue); if (!op) return FALSE; - + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOpQueue::run_next_op\n"); return FALSE; } @@ -130,9 +154,11 @@ camel_op_queue_run_next_op (CamelOpQueue *queue) void camel_op_queue_set_service_availability (CamelOpQueue *queue, gboolean available) { + CAMEL_LOG_FULL_DEBUG ("Entering CamelOpQueue::set_service_availability\n"); g_static_mutex_lock (&op_queue_mutex); queue->service_available = available; g_static_mutex_unlock (&op_queue_mutex); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOpQueue::set_service_availability\n"); } /** @@ -147,9 +173,12 @@ gboolean camel_op_queue_get_service_availability (CamelOpQueue *queue) { gboolean available; + + CAMEL_LOG_FULL_DEBUG ("Entering CamelOpQueue::get_service_availability\n"); g_static_mutex_lock (&op_queue_mutex); available = queue->service_available; g_static_mutex_unlock (&op_queue_mutex); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelOpQueue::get_service_availability\n"); return available; } diff --git a/camel/camel-op-queue.h b/camel/camel-op-queue.h index f649532426..5231a209f6 100644 --- a/camel/camel-op-queue.h +++ b/camel/camel-op-queue.h @@ -45,6 +45,7 @@ typedef struct /* public methods */ CamelOpQueue *camel_op_queue_new (); +void camel_op_queue_free (CamelOpQueue *op_queue); void camel_op_queue_push_op (CamelOpQueue *queue, CamelOp *op); CamelOp *camel_op_queue_pop_op (CamelOpQueue *queue); gboolean camel_op_queue_run_next_op (CamelOpQueue *queue); diff --git a/camel/camel.c b/camel/camel.c index 706041879f..06e0b34f0c 100644 --- a/camel/camel.c +++ b/camel/camel.c @@ -20,11 +20,18 @@ * USA */ +#include #include "camel.h" gint camel_init() { - return data_wrapper_repository_init (); +#ifdef G_THREADS_ENABLED + g_thread_init (NULL); +#else /* G_THREADS_ENABLED */ + printf ("Threads are not supported by glib\n"); +#endif /* G_THREADS_ENABLED */ + + //return data_wrapper_repository_init (); } diff --git a/camel/camel.h b/camel/camel.h index 9950014f8b..085f53fc23 100644 --- a/camel/camel.h +++ b/camel/camel.h @@ -52,6 +52,7 @@ extern "C" { #include #include #include +#include #include #include #include -- cgit v1.2.3