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 _______________________________________________ evolution-hackers mailing list evolution-hackers@gnome.org To change your list options or unsubscribe, visit ... http://mail.gnome.org/mailman/listinfo/evolution-hackers