diff options
author | Not Zed <NotZed@Ximian.com> | 2003-09-18 05:19:04 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2003-09-18 05:19:04 +0800 |
commit | 81a0ff5bc44a3bd11399e6b3c985735737606c8c (patch) | |
tree | 54b5ed4342a6843c1db4c7e75f2e1b1fe9b82dff /mail/em-sync-stream.c | |
parent | a36a1bb70b6ebcb51ac39304370c89bda63e11b9 (diff) | |
download | gsoc2013-evolution-81a0ff5bc44a3bd11399e6b3c985735737606c8c.tar.gz gsoc2013-evolution-81a0ff5bc44a3bd11399e6b3c985735737606c8c.tar.zst gsoc2013-evolution-81a0ff5bc44a3bd11399e6b3c985735737606c8c.zip |
cvs removed.
2003-09-17 Not Zed <NotZed@Ximian.com>
* folder-browser.c, folder-browser.h, folder-browser-ui.c
folder-browser-ui.h, mail-callbacks.c, mail-callbacks.h
mail-display.c, mail-display.h, mail-display-stream.c
mail-display-stream.h, mail-format.c, mail-format.h
mail-identify.c, mail-search.c, mail-search.h
message-browser.c, message-browser.h, subscribe-dialog.c
subscribe-dialog.h, mail-font-prefs.c, mail-font-prefs.h: cvs
removed.
* Makefile.am: Removed mail-font-prefs.[ch], hasn't been built for
ages.
* em-*.c: killed a bunch of printfs.
* em-format-html-display.c (efhd_html_button_press_event): update
for html object api chagnes.
** Merge in mail-refactor-2 branch.
svn path=/trunk/; revision=22602
Diffstat (limited to 'mail/em-sync-stream.c')
-rw-r--r-- | mail/em-sync-stream.c | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/mail/em-sync-stream.c b/mail/em-sync-stream.c new file mode 100644 index 0000000000..df5659253e --- /dev/null +++ b/mail/em-sync-stream.c @@ -0,0 +1,286 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * Michael Zucchi <notzed@ximian.com> + * + * Copyright 2001 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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. + * + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <stdio.h> +#include <camel/camel-stream.h> +#include <camel/camel-object.h> +#include <gtk/gtkmain.h> +#include "em-sync-stream.h" + +#include "mail-mt.h" + +/*#define LOG_STREAM*/ + +#define d(x) + +#define EMSS_CLASS(x) ((EMSyncStreamClass *)(((CamelObject *)(x))->klass)) + +struct _EMSyncStreamPrivate { + /* FIXME: use a single data port/gui channel for all instances */ + /* TODO: possibly just use one of the mail-mt ports ... */ + struct _EMsgPort *data_port, *reply_port; + struct _GIOChannel *gui_channel; + guint gui_watch; + + char *buf_data; + int buf_used; + int buf_size; +}; + +/* Should probably expose messages to outside world ... so subclasses can extend */ +enum _write_msg_t { + EMSS_WRITE, + EMSS_FLUSH, + EMSS_CLOSE, +}; + +struct _write_msg { + EMsg msg; + + enum _write_msg_t op; + + const char *data; + size_t n; +}; + +static void em_sync_stream_class_init (EMSyncStreamClass *klass); +static void em_sync_stream_init (CamelObject *object); +static void em_sync_stream_finalize (CamelObject *object); + +static ssize_t stream_write(CamelStream *stream, const char *buffer, size_t n); +static int stream_close(CamelStream *stream); +static int stream_flush(CamelStream *stream); + +static CamelStreamClass *parent_class = NULL; + +CamelType +em_sync_stream_get_type (void) +{ + static CamelType type = CAMEL_INVALID_TYPE; + + if (type == CAMEL_INVALID_TYPE) { + type = camel_type_register (CAMEL_STREAM_TYPE, + "EMSyncStream", + sizeof (EMSyncStream), + sizeof (EMSyncStreamClass), + (CamelObjectClassInitFunc) em_sync_stream_class_init, + NULL, + (CamelObjectInitFunc) em_sync_stream_init, + (CamelObjectFinalizeFunc) em_sync_stream_finalize); + } + + return type; +} + +static void +em_sync_stream_class_init (EMSyncStreamClass *klass) +{ + CamelStreamClass *stream_class = CAMEL_STREAM_CLASS (klass); + + parent_class = (CamelStreamClass *) CAMEL_STREAM_TYPE; + + /* virtual method overload */ + stream_class->write = stream_write; + stream_class->flush = stream_flush; + stream_class->close = stream_close; +} + +static gboolean +emcs_gui_received(GIOChannel *source, GIOCondition cond, void *data) +{ + EMSyncStream *emss = data; + struct _EMSyncStreamPrivate *p = emss->priv; + struct _write_msg *msg; + + d(printf("%p: gui sync op job waiting\n", emss)); + + msg = (struct _write_msg *)e_msgport_get(p->data_port); + /* Should never happen ... */ + if (msg == NULL) + return TRUE; + + d(printf("%p: running sync op %d\n", emss, msg->op)); + + /* force out any pending data before doing anything else */ + if (p->buf_used > 0) { + EMSS_CLASS(emss)->sync_write((CamelStream *)emss, p->buf_data, p->buf_used); + p->buf_used = 0; + } + + /* FIXME: need to handle return values */ + + switch (msg->op) { + case EMSS_WRITE: + EMSS_CLASS(emss)->sync_write((CamelStream *)emss, msg->data, msg->n); + break; + case EMSS_FLUSH: + EMSS_CLASS(emss)->sync_flush((CamelStream *)emss); + break; + case EMSS_CLOSE: + EMSS_CLASS(emss)->sync_close((CamelStream *)emss); + break; + } + + e_msgport_reply((EMsg *)msg); + d(printf("%p: gui sync op jobs done\n", emss)); + + return TRUE; +} + +static void +em_sync_stream_init (CamelObject *object) +{ + EMSyncStream *emss = (EMSyncStream *)object; + struct _EMSyncStreamPrivate *p; + + p = emss->priv = g_malloc0(sizeof(*p)); + + p->data_port = e_msgport_new(); + p->reply_port = e_msgport_new(); + + p->gui_channel = g_io_channel_unix_new(e_msgport_fd(p->data_port)); + p->gui_watch = g_io_add_watch(p->gui_channel, G_IO_IN, emcs_gui_received, emss); + + d(printf("%p: new emss\n", emss)); +} + +static void +sync_op(EMSyncStream *emss, enum _write_msg_t op, const char *data, size_t n) +{ + struct _EMSyncStreamPrivate *p = emss->priv; + struct _write_msg msg; + + d(printf("%p: launching sync op %d\n", emss, op)); + + /* we do everything synchronous, we should never have any locks, and + this prevents overflow from banked up data */ + + msg.msg.reply_port = p->reply_port; + msg.op = op; + msg.data = data; + msg.n = n; + + e_msgport_put(p->data_port, &msg.msg); + e_msgport_wait(p->reply_port); + + g_assert(e_msgport_get(msg.msg.reply_port) == &msg.msg); + d(printf("%p: returned sync op %d\n", emss, op)); +} + +static void +em_sync_stream_finalize (CamelObject *object) +{ + EMSyncStream *emss = (EMSyncStream *)object; + struct _EMSyncStreamPrivate *p = emss->priv; + + /* TODO: is this stuff safe to do in another thread? */ + g_source_remove(p->gui_watch); + g_io_channel_unref(p->gui_channel); + + e_msgport_destroy(p->data_port); + e_msgport_destroy(p->reply_port); + + p->data_port = NULL; + p->reply_port = NULL; + + g_free(p->buf_data); + g_free(p); +} + +static ssize_t +stream_write (CamelStream *stream, const char *buffer, size_t n) +{ + EMSyncStream *emss = EM_SYNC_STREAM (stream); + struct _EMSyncStreamPrivate *p = emss->priv; + + if (emss->cancel) + return -1; + + if (pthread_self() == mail_gui_thread) + EMSS_CLASS(emss)->sync_write(stream, buffer, n); + else if (p->buf_size > 0) { + size_t left = p->buf_size-p->buf_used; + + if (n >= left) { + sync_op(emss, EMSS_WRITE, buffer, n); + } else { + memcpy(p->buf_data + p->buf_used, buffer, n); + p->buf_used += n; + } + } else { + sync_op(emss, EMSS_WRITE, buffer, n); + } + + return (ssize_t) n; +} + +static int +stream_flush(CamelStream *stream) +{ + EMSyncStream *emss = (EMSyncStream *)stream; + + if (emss->cancel) + return -1; + + if (pthread_self() == mail_gui_thread) + return ((EMSyncStreamClass *)(((CamelObject *)emss)->klass))->sync_flush(stream); + else + sync_op(emss, EMSS_FLUSH, NULL, 0); + + return 0; +} + +static int +stream_close(CamelStream *stream) +{ + EMSyncStream *emss = (EMSyncStream *)stream; + + if (emss->cancel) + return -1; + + d(printf("%p: closing stream\n", stream)); + + if (pthread_self() == mail_gui_thread) + return ((EMSyncStreamClass *)(((CamelObject *)emss)->klass))->sync_close(stream); + else + sync_op(emss, EMSS_CLOSE, NULL, 0); + + return 0; +} + +void +em_sync_stream_set_buffer_size(EMSyncStream *emss, size_t size) +{ + struct _EMSyncStreamPrivate *p = emss->priv; + + g_free(p->buf_data); + p->buf_data = g_malloc(size); + p->buf_size = size; + p->buf_used = 0; +} |