Re: [Evolution-hackers] Camel Manifesto (update)



Here's another update on how the Camel API upgrades are coming along.
My initial roadmap from 2009 is referenced in [1], and my last update
was in May [2].

This next round of API changes will be fairly disruptive, so I'd like to
coordinate with anyone finishing up their own Camel branch so my changes
don't stomp on your work.  I know Chen is finishing his Maildir branch,
so unless I hear from someone else I'll plan to commit as soon as Chen's
changes are in.

The changes are substantial, but the result is pretty straight-forward
and boring.  Most of these changes were presented as future goals in my
May update [2].  There's three major changes:


1. Redefine CamelOperation
--------------------------

I'm removing the whole thread-private CamelOperation concept, along with
the register/unregister functions.  Thread-private CamelOperations seem
convenient but actually have a detrimental effect on the public API and
is one of the major problems I have with Camel: you can't tell from the
API which functions block and which ones don't.  As a result, Evolution
is still rife with Camel calls that block the main loop and hang the UI.

The forthcoming changes will finally solve this design flaw.  As in GIO,
all blocking functions will take a GCancellable pointer.

Since CamelOperation is now a subclass of GCancellable, any GCancellable
pointer in Camel may be a CamelOperation, a plain GCancellable, or NULL.

I've made some further simplifications to CamelOperation both internally
and externally.  The internal message stack is simpler now, and as such
camel_operation_start() and camel_operation_end() have been renamed to
camel_operation_push_message() and camel_operation_pop_message(), which
I think are more intuitive.

Transient operations are now implicit: if you push a new status message
onto a non-empty message stack, the message is treated as transient.  A
transient message just means there's a longer delay before the message
is shown in Evolution's status bar, since transient operations tend to
come and go quickly.  If the transient operation finishes before the
timer expires, the transient message is never shown at all.  This helps
filter out messages that would otherwise flash by too quickly for users
to read.

Finally, passing NULL to any CamelOperation function is now a no-op.


2. Rename Blocking Methods
--------------------------

Almost[*] all blocking method names have grown a "_sync" suffix.  This
has a couple advantages:

- It's pretty damn obvious now when you're making a blocking Camel call
  from Evolution or some other client program.

- Blocking Camel calls are now pretty easy to grep for (camel_.*_sync).
  We can finally track down those blocking the main loop and file bugs.

Methods already using the word "sync" I've expanded to "synchronize" so
the name isn't too weird.  So for example, camel_folder_sync() is now
camel_folder_synchronize_sync().


[*] I didn't bother renaming CamelStream methods, since I plan to
    replace then with GIO streams in the near future and clients
    generally don't call stream methods directly anyway.


3. Asynchronous Methods
-----------------------

All the upgrades I've been making to Camel over the past year, and all
the changes described above were in preparation for this: Camel now has
an asynchronous public API.

Let me immediately point out that there is ZERO IMPACT TO EXISTING CAMEL
PROVIDERS beyond the API changes I mentioned above.  Camel providers
need not do anything special to support the new asynchronous methods.
As in GIO, all async methods default to simply calling the corresponding
synchronous method from a thread pool, which is all Evolution does.

The asynchronous methods will take the old blocking method names in
order to emphasize to clients that this is now the recommended way to
use Camel.  (In case it wasn't already obvious, no I don't care about
Camel's backward-compatibility right now.)


Here's a before and after example to help make this all concrete.

Before:

    gboolean
    camel_folder_append_message        (CamelFolder *folder,
                                        CamelMimeMessage *message,
                                        const CamelMessageInfo *info,
                                        gchar **appended_uid,
                                        GError **error)

After:

    void
    camel_folder_append_message        (CamelFolder *folder,
                                        CamelMimeMessage *message,
                                        CamelMessageInfo *info,
                                        gint io_priority,
                                        GCancellable *cancellable,
                                        GAsyncReadyCallback callback,
                                        gpointer user_data)

    gboolean
    camel_folder_append_message_finish (CamelFolder *folder,
                                        GAsyncResult *result,
                                        gchar **appended_uid,
                                        GError **error)

    gboolean
    camel_folder_append_message_sync   (CamelFolder *folder,
                                        CamelMimeMessage *message,
                                        CamelMessageInfo *info,
                                        gchar **appended_uid,
                                        GCancellable *cancellable,
                                        GError **error)


The next step is to begin tearing into Evolution's clumsy old async
wrappers for Camel, removing the trivial ones and repackaging the rest
using GIO's async pattern.  The MailMsg infrastructure in mail-mt.c will
probably die, since EActivity fills that role now.

I'm also going to start replacing CamelStreams with GIO streams on a
private branch which probably won't land until after the April release.
Hopefully by then GIO will have TLS support, or else I'll have to figure
out an interim solution.

Looking even further out, I plan to leave the MIME stream filters alone
until CamelStream is replaced, and then eventually port them all to the
GConverter interface (complete with extensive unit tests).  But I don't
see that happening until well into next year.


Matthew Barnes


[1] http://mail.gnome.org/archives/evolution-hackers/2009-November/msg00019.html
[2] http://mail.gnome.org/archives/evolution-hackers/2010-May/msg00000.html




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]