Re: [Evolution-hackers] Subclassable and extendable IMAPX



On Wed, 2012-05-23 at 18:40 +0200, Christian Hilberg wrote:
> As dwmw2 just pointed out on IRC, it really isn't.
> The data structures which the derivative untagged handlers
> need to access can/should best be bound to the derivative
> CamelIMAPXServer. In fact, that is exactly the way it works
> in my 2.30 approach, only the data structures were not bound
> to a derivative, but to the original CamelIMAPXServer. Binding
> to the subclass would be the only change needed here.

I'm not letting myself get sucked into this enough to go read IMAPX code
right now so this might be off the mark, but another pattern to consider
is to define a base struct that represents a response:

   struct _CamelIMAPXResponse {
           volatile gint ref_count;

           /* the hash table key */
           const gchar *token;

           /* the server that created this */
           CamelIMAPXServer *is;

           void  (*handle)  (CamelIMAPXResponse *response);
           void  (*destroy) (CamelIMAPXResponse *response);
   };

You could then extend the struct for various tokens and embed the
payload directly in the extended response struct:

   struct _MyCustomResponse {
           CamelIMAPXResponse parent;

           /* response-specific payload goes here */
   };

The benefit here is the response handler function and the payload stay
together at all times, and the extended struct knows how to clean up its
own payload through its destroy function.

Then for each type of extended response struct you write a factory
function that just allocates and initializes an instance of your
extended response struct, but casts it to a CamelIMAPXResponse:

   CamelIMAPXResponse * my_custom_response_new (CamelIMAPXServer *is);

Then in the token table that lives in CamelIMAPXServer, instead of
registering direct handler functions for various tokens you register
these factory functions.

So the server logic looks something like:

   typedef CamelIMAPXResponse *
   (*CamelIMAPXResponseNewFunc) (CamelIMAPXServer *is);

   CamelIMAPXResponseNewFunc new_response_func;
   CamelIMAPXResponse *response;

   /* Look up a factory function for the given token. */
   new_response_func = g_hash_table_lookup (hash_table, token);

   /* Create a new response instance. */
   response = response_new_func (is);

   ...

   /* Invoke the handler function. */
   response->handle (response);

   ...

   /* Unref the response.  If the ref_count reaches
    * zero the response's destroy function is called. */
   camel_imapx_response_unref (response);

Maybe this is overkill for this particular issue since I'm not familiar
with the use cases for the payload data you speak of.

It's certainly more tedious to write in C but offers more flexibility
than a mere function pointer.

Matthew Barnes



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