diff options
-rw-r--r-- | camel/Makefile.am | 4 | ||||
-rw-r--r-- | camel/camel-folder-pt-proxy.c | 183 | ||||
-rw-r--r-- | camel/camel-folder-pt-proxy.h | 9 | ||||
-rw-r--r-- | camel/camel-folder.c | 25 | ||||
-rw-r--r-- | camel/camel-folder.h | 16 | ||||
-rw-r--r-- | camel/camel-marshal-utils.c | 168 | ||||
-rw-r--r-- | camel/camel-marshal-utils.h | 59 | ||||
-rw-r--r-- | camel/camel-op-queue.c | 77 | ||||
-rw-r--r-- | camel/camel-op-queue.h | 12 |
9 files changed, 446 insertions, 107 deletions
diff --git a/camel/Makefile.am b/camel/Makefile.am index 553e153495..8bc72c829e 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = providers +SUBDIRS = #providers libcamelincludedir = $(includedir)/camel @@ -37,6 +37,7 @@ libcamel_la_SOURCES = \ camel-folder.c \ camel-folder-summary.c \ camel-medium.c \ + camel-marshal-utils.c \ camel-mime-body-part.c \ camel-mime-message.c \ camel-mime-part.c \ @@ -71,6 +72,7 @@ libcamelinclude_HEADERS = \ camel-folder.h \ camel-folder-summary.h \ camel-mime-body-part.h \ + camel-marshal-utils.h \ camel-medium.h \ camel-mime-message.h \ camel-mime-part.h \ diff --git a/camel/camel-folder-pt-proxy.c b/camel/camel-folder-pt-proxy.c index f6a5dc5bc0..bfc5900573 100644 --- a/camel/camel-folder-pt-proxy.c +++ b/camel/camel-folder-pt-proxy.c @@ -26,6 +26,7 @@ #include <config.h> #include "camel-folder-pt-proxy.h" #include "camel-log.h" +#include "camel-marshal-utils.h" #include <pthread.h> #include <unistd.h> #include <string.h> @@ -42,8 +43,23 @@ static CamelFolderClass *parent_class=NULL; #define CFPP_CLASS(so) CAMEL_FOLDER_PT_PROXY_CLASS (GTK_OBJECT(so)->klass) #define CF_CLASS(so) CAMEL_FOLDER_CLASS (GTK_OBJECT(so)->klass) + +enum CamelFolderFunc { + CAMEL_FOLDER_OPEN, + CAMEL_FOLDER_CLOSE, + CAMEL_FOLDER__LAST_FUNC +}; + +static CamelFuncDef _camel_func_def [CAMEL_FOLDER__LAST_FUNC]; + + + static void _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex); -static void _open (CamelFolder *folder, CamelFolderOpenMode mode, 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 _set_name (CamelFolder *folder, const gchar *name, CamelException *ex); static const gchar *_get_name (CamelFolder *folder, CamelException *ex); @@ -174,40 +190,16 @@ _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) +void +_op_run_free_notify (CamelOp *op) { - CamelOpQueue *op_queue; - pthread_t thread; + gboolean error; + + error = camel_op_run (op); + camel_op_free (op); - op_queue = proxy_folder->op_queue; - - if (camel_op_queue_get_service_availability (op_queue)) { - /* no thread is currently running, run - * the operation directly */ - camel_op_queue_set_service_availability (op_queue, FALSE); - pthread_create (&thread, NULL , (thread_call_func)(op->func), op->param); - camel_op_free (op); - } else { - /* a child thread is already running, - * push the operation in the queue */ - camel_op_queue_push_op (op_queue, op); - } - } - - /** * _maybe_run_next_op: run next operation in queue, if any * @proxy_folder: @@ -230,10 +222,44 @@ _maybe_run_next_op (CamelFolderPtProxy *proxy_folder) } /* run the operation in a child thread */ - pthread_create (&thread, NULL , (thread_call_func)(op->func), op->param); - camel_op_free (op); + pthread_create (&thread, NULL, (thread_call_func) camel_op_run_and_free, op); + } +static void +_maybe_run_next_op_in_thread (CamelFolderPtProxy *proxy_folder) +{ + +} + + +/** + * _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) +{ + CamelOpQueue *op_queue; + pthread_t thread; + + op_queue = proxy_folder->op_queue; + 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.*/ + camel_op_queue_set_service_availability (op_queue, FALSE); + _maybe_run_next_op (proxy_folder); + } +} + + + @@ -453,41 +479,10 @@ _thread_notification_catch (GIOChannel *source, */ /* folder->init_with_store implementation */ - -typedef struct { - CamelFolder *folder; - CamelStore *parent_store; - CamelException *ex; -} _InitStoreParam; - -static void -_async_init_with_store (gpointer param) -{ - _InitStoreParam *init_store_param; - CamelFolder *folder; - CamelException *ex; - - init_store_param = (_InitStoreParam *)param; - - folder = init_store_param->folder; - - CF_CLASS (folder)->init_with_store (folder, - init_store_param->parent_store, - NULL); - g_free (param); - - /* tell the main thread we are completed */ - _notify_availability (folder, 'a'); - -} - - static void _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex) { CamelFolderPtProxy *proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); - _InitStoreParam *param; - CamelOp *op; #warning Notify io_channel initialization should be elsewhere /* it can not be in camel_folder_proxy_init @@ -497,17 +492,9 @@ _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException "proxy_folder", proxy_folder); - op = camel_op_new (); - /* param will be freed in _async_init_with_store */ - param = g_new (_InitStoreParam, 1); - param->folder = proxy_folder->real_folder; - param->parent_store = parent_store; - - op->func = _async_init_with_store; - op->param = param; - - _op_exec_or_plan_for_exec (proxy_folder, op); - + camel_folder_init_with_store (proxy_folder->real_folder, + parent_store, + ex); } @@ -517,9 +504,40 @@ _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException 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; + + + + + 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; + + +} + static void _async_open (gpointer param) { @@ -532,15 +550,23 @@ _async_open (gpointer param) folder = open_folder_param->folder; CF_CLASS (folder)->open (folder, - open_folder_param->mode, + open_folder_param->mode, + open_folder_param->callback, + open_folder_param->user_data, NULL); g_free (param); _notify_availability (folder, 'a'); } + + static void -_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) +_open (CamelFolder *folder, + CamelFolderOpenMode mode, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex) { CamelFolderPtProxy *proxy_folder = CAMEL_FOLDER_PT_PROXY (folder); _OpenFolderParam *param; @@ -551,7 +577,10 @@ _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) 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; diff --git a/camel/camel-folder-pt-proxy.h b/camel/camel-folder-pt-proxy.h index 50b9887adb..39f6ee3d16 100644 --- a/camel/camel-folder-pt-proxy.h +++ b/camel/camel-folder-pt-proxy.h @@ -42,6 +42,8 @@ typedef struct { GtkArg *args; } PtProxySignaData; + + typedef struct { CamelFolder parent; @@ -66,6 +68,13 @@ typedef struct { } CamelFolderPtProxyClass; +/* some marshallers */ +void camel_marshal_NONE__POINTER_INT (CamelFunc func, + GtkArg *args); + +void camel_marshal_NONE__POINTER_INT_POINTER (CamelFunc func, + GtkArg *args); + diff --git a/camel/camel-folder.c b/camel/camel-folder.c index adcc7fc423..f887d83ad0 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -31,7 +31,11 @@ static GtkObjectClass *parent_class=NULL; #define CF_CLASS(so) CAMEL_FOLDER_CLASS (GTK_OBJECT(so)->klass) static void _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex); -static void _open (CamelFolder *folder, CamelFolderOpenMode mode, 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 _set_name (CamelFolder *folder, const gchar *name, CamelException *ex); /* static void _set_full_name (CamelFolder *folder, const gchar *name); */ @@ -193,16 +197,25 @@ _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException * **/ static void -_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) +_open (CamelFolder *folder, + CamelFolderOpenMode mode, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex) { - folder->open_state = FOLDER_OPEN; - folder->open_mode = mode; +/* folder->open_state = FOLDER_OPEN; */ +/* folder->open_mode = mode; */ } -void camel_folder_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) +void +camel_folder_open (CamelFolder *folder, + CamelFolderOpenMode mode, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex) { - CF_CLASS(folder)->open (folder, mode, ex); + CF_CLASS(folder)->open (folder, mode, callback, user_data, ex); } diff --git a/camel/camel-folder.h b/camel/camel-folder.h index 05becd64b0..7f454d92e5 100644 --- a/camel/camel-folder.h +++ b/camel/camel-folder.h @@ -57,7 +57,7 @@ typedef enum { FOLDER_OPEN_RW = 3 /* folder is read/write */ } CamelFolderOpenMode; - +typedef void (*CamelFolderAsyncCallback) (); struct _CamelFolder { @@ -89,7 +89,11 @@ typedef struct { /* Virtual methods */ void (*init_with_store) (CamelFolder *folder, CamelStore *parent_store, CamelException *ex); - void (*open) (CamelFolder *object, CamelFolderOpenMode mode, CamelException *ex); + void (*open) (CamelFolder *folder, + CamelFolderOpenMode mode, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex); void (*close) (CamelFolder *folder, gboolean expunge, CamelException *ex); void (*set_name) (CamelFolder *folder, const gchar *name, CamelException *ex); /* void (*set_full_name) (CamelFolder *folder, const gchar *name); */ @@ -128,7 +132,13 @@ GtkType camel_folder_get_type (void); /* public methods */ CamelFolder *camel_folder_get_folder (CamelFolder *folder, gchar *folder_name, CamelException *ex); -void camel_folder_open (CamelFolder *folder, CamelFolderOpenMode mod, CamelException *exe); + +void camel_folder_open (CamelFolder *folder, + CamelFolderOpenMode mode, + CamelFolderAsyncCallback callback, + gpointer user_data, + CamelException *ex); + void camel_folder_close (CamelFolder *folder, gboolean expunge, CamelException *ex); gboolean camel_folder_create (CamelFolder *folder, CamelException *ex); gboolean camel_folder_delete (CamelFolder *folder, gboolean recurse, CamelException *ex); diff --git a/camel/camel-marshal-utils.c b/camel/camel-marshal-utils.c new file mode 100644 index 0000000000..95cf1577bb --- /dev/null +++ b/camel/camel-marshal-utils.c @@ -0,0 +1,168 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-marshal-utils.c : marshal utils */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf <Bertrand.Guiheneuf@aful.org> . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + + + +#include "config.h" +#include "camel-log.h" +#include "camel-marshal-utils.h" + + +CamelFuncDef * +camel_func_def_new (CamelMarshal marshal, guint n_params, ...) +{ + CamelFuncDef *func_def; + va_list args; + GtkType type; + int i; + + func_def = g_new (CamelFuncDef, 1); + func_def->marshal = marshal; + func_def->n_params = n_params; + func_def->params_type = g_new (GtkType, n_params); + + va_start (args, n_params); + for (i=0; i<n_params; i++) { + type = va_arg (args, GtkType); + func_def->params_type [i] = type; + } + va_end (args); + + return func_def; +} + + + + +static gboolean +_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++) + { + register gchar *error; + + params->name = NULL; + params->type = *(func_def->params_type++); + GTK_ARG_COLLECT_VALUE (params, + var_args, + error); + if (error) + { + failed = TRUE; + CAMEL_LOG_FULL_DEBUG ("CamelMarshall::_collect_params(): %s", error); + g_free (error); + } + } + return (failed); +} + + +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); +} + + +CamelOp * +camel_marshal_create_op (CamelFuncDef *func_def, ...) +{ + GtkArg *params; + gboolean error; + CamelOp *op; + va_list args; + + g_assert (func_def); + + op = camel_op_new (func_def); + + va_start (args, func_def); + error = _collect_params (op->params, func_def, args); + va_end (args); + + if (error) { + camel_op_free (op); + return NULL; + } else + return (op); +} + + + + + + + +/* misc marshaller */ + + +typedef void (*CamelMarshal_NONE__POINTER_INT) (gpointer arg1, + gint arg2); +void camel_marshal_NONE__POINTER_INT (CamelFunc func, + GtkArg *args) +{ + CamelMarshal_NONE__POINTER_INT rfunc; + rfunc = (CamelMarshal_NONE__POINTER_INT) func; + (* rfunc) (GTK_VALUE_POINTER(args[0]), + GTK_VALUE_INT(args[1])); +} + + + + + +typedef void (*CamelMarshal_NONE__POINTER_INT_POINTER) (gpointer arg1, + gint arg2, + gpointer arg3); +void camel_marshal_NONE__POINTER_INT_POINTER (CamelFunc func, + GtkArg *args) +{ + CamelMarshal_NONE__POINTER_INT_POINTER rfunc; + rfunc = (CamelMarshal_NONE__POINTER_INT_POINTER) func; + (* rfunc) (GTK_VALUE_POINTER(args[0]), + GTK_VALUE_INT(args[1]), + GTK_VALUE_POINTER(args[2])); +} diff --git a/camel/camel-marshal-utils.h b/camel/camel-marshal-utils.h new file mode 100644 index 0000000000..158b72b1be --- /dev/null +++ b/camel/camel-marshal-utils.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-maeshal-utils.h : marshal utils */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf <Bertrand.Guiheneuf@aful.org> . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + + +#ifndef CAMEL_MARSHAL_UTILS_H +#define CAMEL_MARSHAL_UTILS_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +#include <gtk/gtk.h> + +typedef void (*CamelFunc) (); + +typedef gboolean ( *CamelMarshal) (CamelFunc func, + GtkArg *args); + +typedef struct { + CamelMarshal marshal; + CamelFunc func; + guint n_params; + GtkType *params_type; + +} CamelFuncDef; + + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_MARSHAL_UTILS_H */ + diff --git a/camel/camel-op-queue.c b/camel/camel-op-queue.c index d943b8e80b..100a3df89e 100644 --- a/camel/camel-op-queue.c +++ b/camel/camel-op-queue.c @@ -19,11 +19,19 @@ * USA */ + +/* MT safe */ + + #include "camel-op-queue.h" #define NB_OP_CHUNKS 20 static GMemChunk *op_chunk=NULL; +static GStaticMutex op_queue_mutex = G_STATIC_MUTEX_INIT; + + + /** * camel_op_queue_new: create a new operation queue * @@ -35,11 +43,14 @@ CamelOpQueue * 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; op_queue->ops_head = NULL; @@ -61,13 +72,13 @@ camel_op_queue_push_op (CamelOpQueue *queue, CamelOp *op) GList *new_op; g_assert (queue); - + g_static_mutex_lock (&op_queue_mutex); if (!queue->ops_tail) { 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); - + queue->ops_head = g_list_prepend (queue->ops_head, op); + g_static_mutex_unlock (&op_queue_mutex); } @@ -82,14 +93,18 @@ camel_op_queue_push_op (CamelOpQueue *queue, CamelOp *op) CamelOp * camel_op_queue_pop_op (CamelOpQueue *queue) { - GList *op; - + GList *op_list; + CamelOp *op; + g_assert (queue); - - op = queue->ops_tail; + + g_static_mutex_lock (&op_queue_mutex); + op_list = queue->ops_tail; queue->ops_tail = queue->ops_tail->prev; + op = (CamelOp *)op_list->data; + g_static_mutex_unlock (&op_queue_mutex); - return (CamelOp *)op->data; + return op; } @@ -109,8 +124,7 @@ camel_op_queue_run_next_op (CamelOpQueue *queue) op = camel_op_queue_pop_op (queue); if (!op) return FALSE; - /* run the operation */ - op->func (op->param); + return FALSE; } @@ -125,7 +139,9 @@ camel_op_queue_run_next_op (CamelOpQueue *queue) void camel_op_queue_set_service_availability (CamelOpQueue *queue, gboolean available) { - queue->service_available = available; + g_static_mutex_lock (&op_queue_mutex); + queue->service_available = available; + g_static_mutex_unlock (&op_queue_mutex); } /** @@ -139,7 +155,11 @@ camel_op_queue_set_service_availability (CamelOpQueue *queue, gboolean available gboolean camel_op_queue_get_service_availability (CamelOpQueue *queue) { - return queue->service_available; + gboolean available; + g_static_mutex_lock (&op_queue_mutex); + available = queue->service_available; + g_static_mutex_unlock (&op_queue_mutex); + return available; } /** @@ -151,9 +171,15 @@ camel_op_queue_get_service_availability (CamelOpQueue *queue) * Return value: the newly allocated CamelOp object **/ CamelOp * -camel_op_new () +camel_op_new (CamelFuncDef *func_def) { - return g_chunk_new (CamelOp, op_chunk); + 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; } /** @@ -167,7 +193,28 @@ camel_op_new () 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 809946867f..9c91ca9297 100644 --- a/camel/camel-op-queue.h +++ b/camel/camel-op-queue.h @@ -30,13 +30,13 @@ extern "C" { #endif /* __cplusplus }*/ #include <glib.h> +#include "camel-marshal-utils.h" -typedef void (CamelOpFunc)(gpointer param); -typedef struct { - CamelOpFunc *func; - gpointer param; +typedef struct { + CamelFuncDef *func_def; + GtkArg *params; } CamelOp; @@ -57,8 +57,10 @@ 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 (); +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 |