diff options
-rw-r--r-- | camel/Makefile.am | 2 | ||||
-rw-r--r-- | camel/camel-folder-pt-proxy.c | 160 | ||||
-rw-r--r-- | camel/camel-folder-pt-proxy.h | 2 | ||||
-rw-r--r-- | camel/camel-marshal-utils.c | 195 | ||||
-rw-r--r-- | camel/camel-marshal-utils.h | 38 | ||||
-rw-r--r-- | camel/camel-op-queue.c | 65 | ||||
-rw-r--r-- | camel/camel-op-queue.h | 11 | ||||
-rw-r--r-- | camel/camel.h | 3 | ||||
-rw-r--r-- | tests/Makefile.am | 14 |
9 files changed, 320 insertions, 170 deletions
diff --git a/camel/Makefile.am b/camel/Makefile.am index 8bc72c829e..474718ddf5 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -98,6 +98,8 @@ libcamelinclude_HEADERS = \ url-util.h \ $(pthread_HDR) +libcamel_extra_sources = \ + camel-arg-collector.c libcamel_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir) diff --git a/camel/camel-folder-pt-proxy.c b/camel/camel-folder-pt-proxy.c index bfc5900573..9c52615971 100644 --- a/camel/camel-folder-pt-proxy.c +++ b/camel/camel-folder-pt-proxy.c @@ -94,13 +94,18 @@ static void _finalize (GtkObject *object); 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) { GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_folder_pt_proxy_class); CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_folder_pt_proxy_class); - + CamelFolderPtProxyClass *proxy_class = camel_folder_pt_proxy_class; + parent_class = gtk_type_class (camel_folder_get_type ()); /* virtual method definition */ @@ -133,6 +138,12 @@ camel_folder_pt_proxy_class_init (CamelFolderPtProxyClass *camel_folder_pt_proxy /* virtual method overload */ gtk_object_class->finalize = _finalize; + + /* function definition for proxying */ + proxy_class->open_func_def = + camel_func_def_new (camel_marshal_NONE__POINTER_INT_POINTER_POINTER, + 1, + GTK_TYPE_INT); } @@ -144,10 +155,13 @@ 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); } + GtkType camel_folder_pt_proxy_get_type (void) { @@ -188,26 +202,54 @@ _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_notify (CamelOp *op) +_op_run_free_and_notify (CamelOp *op) { gboolean error; - - error = camel_op_run (op); + CamelFolder *folder; + + camel_op_run (op); camel_op_free (op); - + folder = camel_op_get_user_data (op); + _notify_availability (folder, 'a'); } + + + /** - * _maybe_run_next_op: run next operation in queue, if any + * _run_next_op_in_thread: * @proxy_folder: * - * + * run the next operation pending in the proxy + * operation queue **/ static void -_maybe_run_next_op (CamelFolderPtProxy *proxy_folder) +_run_next_op_in_thread (CamelFolderPtProxy *proxy_folder) { CamelOp *op; CamelOpQueue *op_queue; @@ -222,17 +264,12 @@ _maybe_run_next_op (CamelFolderPtProxy *proxy_folder) } /* run the operation in a child thread */ - pthread_create (&thread, NULL, (thread_call_func) camel_op_run_and_free, op); - -} + pthread_create (&thread, NULL, (thread_call_func) _op_run_free_and_notify, op); -static void -_maybe_run_next_op_in_thread (CamelFolderPtProxy *proxy_folder) -{ - } + /** * _op_exec_or_plan_for_exec: * @proxy_folder: @@ -249,12 +286,27 @@ _op_exec_or_plan_for_exec (CamelFolderPtProxy *proxy_folder, CamelOp *op) 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 operation next op.*/ + * the next operation. */ camel_op_queue_set_service_availability (op_queue, FALSE); - _maybe_run_next_op (proxy_folder); + /* 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); } } @@ -298,7 +350,7 @@ _init_notify_system (CamelFolderPtProxy *proxy_folder) /** * notify_availability: notify thread completion - * @folder: server folder (in the child thread) + * @folder: real folder (in the child thread) * @op_name: operation name * * called by child thread (real folder) to notify the main @@ -330,6 +382,9 @@ _notify_availability (CamelFolder *folder, gchar op_name) } while (bytes_written == 1); } + + + /* signal proxying */ static void @@ -389,7 +444,7 @@ _signal_marshaller_client_side (CamelFolderPtProxy *proxy_folder) } - +static void _init_signals_proxy (CamelFolderPtProxy *proxy_folder) { CamelFolder *real_folder; @@ -403,7 +458,7 @@ _init_signals_proxy (CamelFolderPtProxy *proxy_folder) real_folder = proxy_folder->real_folder; for (i=0; signal_to_proxy[i]; i++) { - /* conect the signal to the signal marshaller + /* 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], @@ -420,7 +475,7 @@ _init_signals_proxy (CamelFolderPtProxy *proxy_folder) } -/**** catch notification from the child thread ****/ +/**** catch notification from child thread ****/ /** * _thread_notification_catch: call by glib loop when data is available on the thread io channel * @source: @@ -449,7 +504,7 @@ _thread_notification_catch (GIOChannel *source, switch (op_name) { case 'a': /* the thread is OK for a new operation */ - _maybe_run_next_op (proxy_folder); + _run_next_op_in_thread (proxy_folder); break; case 's': /* there is a pending signal to proxy */ _signal_marshaller_client_side (proxy_folder); @@ -492,7 +547,7 @@ _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException "proxy_folder", proxy_folder); - camel_folder_init_with_store (proxy_folder->real_folder, + CF_CLASS (proxy_folder)->init_with_store (proxy_folder->real_folder, parent_store, ex); } @@ -529,11 +584,11 @@ _folder_open_cb (CamelFolder *folder, g_assert (proxy_folder); g_assert (callback); - op = camel_op_new (); + //op = camel_op_new (); - param = g_new (_OpenFolderParam, 1); - param->folder = proxy_folder; - param->user_data = user_data; + //param = g_new (_OpenFolderParam, 1); + //param->folder = proxy_folder; + //param->user_data = user_data; } @@ -572,19 +627,19 @@ _open (CamelFolder *folder, _OpenFolderParam *param; CamelOp *op; - op = camel_op_new (); + //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; + //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->func = _async_open; + //op->param = param; - _op_exec_or_plan_for_exec (proxy_folder, op); + //_op_exec_or_plan_for_exec (proxy_folder, op); } @@ -624,16 +679,16 @@ _close (CamelFolder *folder, gboolean expunge, CamelException *ex) _CloseFolderParam *param; CamelOp *op; - op = camel_op_new (); + //op = camel_op_new (); - param = g_new (_CloseFolderParam, 1); - param->folder = proxy_folder->real_folder; - param->expunge = expunge; + //param = g_new (_CloseFolderParam, 1); + //param->folder = proxy_folder->real_folder; + //param->expunge = expunge; - op->func = _async_close; - op->param = param; + //op->func = _async_close; + //op->param = param; - _op_exec_or_plan_for_exec (proxy_folder, op); + //_op_exec_or_plan_for_exec (proxy_folder, op); } @@ -672,16 +727,16 @@ _set_name (CamelFolder *folder, const gchar *name, CamelException *ex) _SetNameFolderParam *param; CamelOp *op; - op = camel_op_new (); + //op = camel_op_new (); - param = g_new (_SetNameFolderParam, 1); - param->folder = proxy_folder->real_folder; - param->name = name; + //param = g_new (_SetNameFolderParam, 1); + //param->folder = proxy_folder->real_folder; + //param->name = name; - op->func = _async_set_name; - op->param = param; + //op->func = _async_set_name; + //op->param = param; - _op_exec_or_plan_for_exec (proxy_folder, op); + //_op_exec_or_plan_for_exec (proxy_folder, op); } @@ -922,3 +977,8 @@ _get_uid_list (CamelFolder *folder, CamelException *ex) /* **** */ + + + + + diff --git a/camel/camel-folder-pt-proxy.h b/camel/camel-folder-pt-proxy.h index 39f6ee3d16..e540c78d4b 100644 --- a/camel/camel-folder-pt-proxy.h +++ b/camel/camel-folder-pt-proxy.h @@ -65,6 +65,8 @@ typedef struct { typedef struct { CamelFolderClass parent_class; + + CamelFuncDef *open_func_def; } CamelFolderPtProxyClass; diff --git a/camel/camel-marshal-utils.c b/camel/camel-marshal-utils.c index 95cf1577bb..bb12318837 100644 --- a/camel/camel-marshal-utils.c +++ b/camel/camel-marshal-utils.c @@ -27,8 +27,13 @@ #include "config.h" #include "camel-log.h" #include "camel-marshal-utils.h" +#include "camel-arg-collector.c" +#define NB_OP_CHUNKS 20 +static GMemChunk *op_chunk=NULL; +static GStaticMutex op_chunk_mutex = G_STATIC_MUTEX_INIT; + CamelFuncDef * camel_func_def_new (CamelMarshal marshal, guint n_params, ...) { @@ -60,20 +65,22 @@ _collect_params (GtkArg *params, CamelFuncDef *func_def, va_list var_args) { - register GtkArg *last_param; - register gboolean failed = FALSE; - - for (last_param = params + func_def->n_params; - params < last_param; - params++) + GtkArg *last_param; + int i; + gboolean failed = FALSE; + + + for (i=0; + i<func_def->n_params; + i++, params++) { - register gchar *error; + gchar *error; params->name = NULL; - params->type = *(func_def->params_type++); - GTK_ARG_COLLECT_VALUE (params, - var_args, - error); + params->type = (func_def->params_type) [i]; + CAMEL_ARG_COLLECT_VALUE (params, + var_args, + error); if (error) { failed = TRUE; @@ -85,30 +92,20 @@ _collect_params (GtkArg *params, } -gboolean -camel_marshal_exec_func (CamelFuncDef *func_def, ...) -{ - GtkArg *params; - gboolean error; - va_list args; - - g_assert (func_def); - - params = g_new (GtkArg, func_def->n_params); - - va_start (args, func_def); - error = _collect_params (params, func_def, args); - va_end (args); - if (!error) - error = func_def->marshal (func_def->func, params); - - g_free (params); - return (!error); -} - +/** + * camel_marshal_create_op: create an operation + * @func_def: function definition object + * @func: function to call + * + * create a function ready to be executed. The + * vari + * + * + * Return value: operation ready to be executed + **/ CamelOp * -camel_marshal_create_op (CamelFuncDef *func_def, ...) +camel_marshal_create_op (CamelFuncDef *func_def, CamelFunc func, ...) { GtkArg *params; gboolean error; @@ -118,8 +115,9 @@ camel_marshal_create_op (CamelFuncDef *func_def, ...) g_assert (func_def); op = camel_op_new (func_def); - - va_start (args, func_def); + op->func = func; + + va_start (args, func); error = _collect_params (op->params, func_def, args); va_end (args); @@ -133,6 +131,102 @@ camel_marshal_create_op (CamelFuncDef *func_def, ...) +/** + * camel_op_new: return a new CamelOp object + * + * The obtained object must be destroyed with + * camel_op_free () + * + * Return value: the newly allocated CamelOp object + **/ +CamelOp * +camel_op_new (CamelFuncDef *func_def) +{ + CamelOp *op; + + g_static_mutex_lock (&op_chunk_mutex); + if (!op_chunk) + op_chunk = g_mem_chunk_create (CamelOp, + NB_OP_CHUNKS, + G_ALLOC_AND_FREE); + g_static_mutex_unlock (&op_chunk_mutex); + + op = g_chunk_new (CamelOp, op_chunk); + op->func_def = func_def; + op->params = g_new (GtkArg, func_def->n_params); + + return op; +} + +/** + * camel_op_free: free a CamelOp object allocated with camel_op_new + * @op: CamelOp object to free + * + * Free a CamelOp object allocated with camel_op_new () + * this routine won't work with CamelOp objects allocated + * with other allocators. + **/ +void +camel_op_free (CamelOp *op) +{ + g_free (op->params); + g_chunk_free (op, op_chunk); +} + + +/** + * camel_op_run: run an operation + * @op: the operation object + * + * run an operation + * + **/ +void +camel_op_run (CamelOp *op) +{ + GtkArg *params; + gboolean error; + + g_assert (op); + g_assert (op->func_def); + g_assert (op->params); + + op->func_def->marshal (op->func, op->params); +} + + + + +/** + * camel_op_set_user_data: set the private field + * @op: operation + * @user_data: private field + * + * associate a field to an operation object + **/ +void +camel_op_set_user_data (CamelOp *op, gpointer user_data) +{ + g_assert (op); + op->user_data = user_data; +} + + +/** + * camel_op_get_user_data: return the private field + * @op: operation object + * + * return the private field associated to + * an operation object. + * + * Return value: + **/ +gpointer +camel_op_get_user_data (CamelOp *op) +{ + g_assert (op); + return op->user_data; +} @@ -166,3 +260,34 @@ void camel_marshal_NONE__POINTER_INT_POINTER (CamelFunc func, GTK_VALUE_INT(args[1]), GTK_VALUE_POINTER(args[2])); } + +typedef void (*CamelMarshal_NONE__POINTER_INT_POINTER_POINTER) (gpointer arg1, + gint arg2, + gpointer arg3, + gpointer arg4); +void camel_marshal_NONE__POINTER_INT_POINTER_POINTER (CamelFunc func, + GtkArg *args) +{ + CamelMarshal_NONE__POINTER_INT_POINTER_POINTER rfunc; + 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])); +} + + +typedef void (*CamelMarshal_NONE__INT) (gint arg1); +void camel_marshal_NONE__INT (CamelFunc func, + GtkArg *args) +{ + CamelMarshal_NONE__INT rfunc; + rfunc = (CamelMarshal_NONE__INT) func; + (* rfunc) (GTK_VALUE_INT (args[0])); +} + + + + + + diff --git a/camel/camel-marshal-utils.h b/camel/camel-marshal-utils.h index 158b72b1be..324f32e644 100644 --- a/camel/camel-marshal-utils.h +++ b/camel/camel-marshal-utils.h @@ -34,14 +34,19 @@ extern "C" { #include <gtk/gtk.h> + typedef void (*CamelFunc) (); -typedef gboolean ( *CamelMarshal) (CamelFunc func, +typedef void ( *CamelMarshal) (CamelFunc func, GtkArg *args); + + + + typedef struct { + CamelMarshal marshal; - CamelFunc func; guint n_params; GtkType *params_type; @@ -49,7 +54,36 @@ typedef struct { +typedef struct { + CamelFuncDef *func_def; + CamelFunc func; + GtkArg *params; + gpointer user_data; +} CamelOp; + + +CamelFuncDef * +camel_func_def_new (CamelMarshal marshal, + guint n_params, + ...); + + +CamelOp *camel_op_new (CamelFuncDef *func_def); +void camel_op_free (CamelOp *op); +void camel_op_run (CamelOp *op); +void camel_op_run_and_free (CamelOp *op); +void camel_op_set_user_data (CamelOp *op, gpointer user_data); +gpointer camel_op_get_user_data (CamelOp *op); + +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_INT_POINTER_POINTER (CamelFunc func, + GtkArg *args); +void camel_marshal_NONE__INT (CamelFunc func, + GtkArg *args); #ifdef __cplusplus } diff --git a/camel/camel-op-queue.c b/camel/camel-op-queue.c index 100a3df89e..a722c16f80 100644 --- a/camel/camel-op-queue.c +++ b/camel/camel-op-queue.c @@ -25,9 +25,6 @@ #include "camel-op-queue.h" -#define NB_OP_CHUNKS 20 -static GMemChunk *op_chunk=NULL; - static GStaticMutex op_queue_mutex = G_STATIC_MUTEX_INIT; @@ -44,12 +41,6 @@ camel_op_queue_new () { CamelOpQueue *op_queue; - g_static_mutex_lock (&op_queue_mutex); - if (!op_chunk) - op_chunk = g_mem_chunk_create (CamelOp, - NB_OP_CHUNKS, - G_ALLOC_AND_FREE); - g_static_mutex_unlock (&op_queue_mutex); op_queue = g_new (CamelOpQueue, 1); op_queue->ops_tail = NULL; @@ -162,59 +153,3 @@ camel_op_queue_get_service_availability (CamelOpQueue *queue) return available; } -/** - * camel_op_new: return a new CamelOp object - * - * The obtained object must be destroyed with - * camel_op_free () - * - * Return value: the newly allocated CamelOp object - **/ -CamelOp * -camel_op_new (CamelFuncDef *func_def) -{ - CamelOp *op; - - op = g_chunk_new (CamelOp, op_chunk); - op->func_def = func_def; - op->params = g_new (GtkArg, func_def->n_params); - - return op; -} - -/** - * camel_op_free: free a CamelOp object allocated with camel_op_new - * @op: CamelOp object to free - * - * Free a CamelOp object allocated with camel_op_new () - * this routine won't work with CamelOp objects allocated - * with other allocators. - **/ -void -camel_op_free (CamelOp *op) -{ - g_free (op->params); - g_chunk_free (op, op_chunk); -} - - -/** - * camel_op_run: run an operation - * @op: the opertaion object - * - * run an operation - * - * Return value: - **/ -gboolean -camel_op_run (CamelOp *op) -{ - GtkArg *params; - gboolean error; - - g_assert (op); - g_assert (op->func_def); - g_assert (op->params); - - return (op->func_def->marshal (op->func_def->func, op->params)); -} diff --git a/camel/camel-op-queue.h b/camel/camel-op-queue.h index 9c91ca9297..f649532426 100644 --- a/camel/camel-op-queue.h +++ b/camel/camel-op-queue.h @@ -34,12 +34,6 @@ extern "C" { -typedef struct { - CamelFuncDef *func_def; - GtkArg *params; -} CamelOp; - - typedef struct { GList *ops_head; @@ -57,11 +51,6 @@ gboolean camel_op_queue_run_next_op (CamelOpQueue *queue); gboolean camel_op_queue_get_service_availability (CamelOpQueue *queue); void camel_op_queue_set_service_availability (CamelOpQueue *queue, gboolean available); -CamelOp *camel_op_new (CamelFuncDef *func_def); -void camel_op_free (CamelOp *op); -gboolean camel_op_run (CamelOp *op); -gboolean camel_op_run_and_free (CamelOp *op); - #ifdef __cplusplus } diff --git a/camel/camel.h b/camel/camel.h index 33bd0bdd92..9950014f8b 100644 --- a/camel/camel.h +++ b/camel/camel.h @@ -38,10 +38,13 @@ extern "C" { #include <camel/camel-data-wrapper.h> #include <camel-simple-data-wrapper.h> #include <camel-folder.h> +#include <camel-folder-pt-proxy.h> +#include <camel-marshal-utils.h> #include <camel-mime-body-part.h> #include <camel-mime-message.h> #include <camel-mime-part.h> #include <camel-multipart.h> +#include <camel-op-queue.h> #include <camel-provider.h> #include <camel-service.h> #include <camel-session.h> diff --git a/tests/Makefile.am b/tests/Makefile.am index e781124e3b..282ba2018a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,16 +11,16 @@ LDADD = \ -test4_LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/camel/providers/MH/libcamelmh.la \ - $(GNOME_LIBDIR) \ - $(GNOMEUI_LIBS) $(INTLLIBS) $(PTHREAD_LIB) +#test4_LDADD = \ +# $(top_builddir)/camel/libcamel.la \ +# $(top_builddir)/camel/providers/MH/libcamelmh.la \ +# $(GNOME_LIBDIR) \ +# $(GNOMEUI_LIBS) $(INTLLIBS) $(PTHREAD_LIB) noinst_PROGRAMS = \ test1 \ test2 \ test3 \ - test4 \ - test7 + test7 \ + test8 |