diff --git a/degesch.c b/degesch.c index 9a44dad..e0c8904 100644 --- a/degesch.c +++ b/degesch.c @@ -100,12 +100,43 @@ static struct config_item g_config_table[] = return false; \ BLOCK_END -static void user_unref (void *p); -static void channel_unref (void *p); +struct user; +static void user_unref (struct user *self); + +struct channel; +static void channel_unref (struct channel *self); + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// We need a few reference countable objects with support +// for both strong and weak references /// Callback just before a reference counted object is destroyed typedef void (*destroy_cb_fn) (void *object, void *user_data); +#define REF_COUNTABLE_HEADER \ + size_t ref_count; /**< Reference count */ \ + destroy_cb_fn on_destroy; /**< To remove any weak references */ \ + void *user_data; /**< User data for callbacks */ + +#define REF_COUNTABLE_METHODS(name) \ + static struct name * \ + name ## _ref (struct name *self) \ + { \ + self->ref_count++; \ + return self; \ + } \ + \ + static void \ + name ## _unref (struct name *self) \ + { \ + if (--self->ref_count) \ + return; \ + if (self->on_destroy) \ + self->on_destroy (self, self->user_data); \ + name ## _destroy (self); \ + } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - struct user_channel @@ -123,9 +154,8 @@ user_channel_new (void) } static void -user_channel_destroy (void *p) +user_channel_destroy (struct user_channel *self) { - struct user_channel *self = p; channel_unref (self->channel); free (self); } @@ -137,10 +167,7 @@ user_channel_destroy (void *p) struct user { - size_t ref_count; ///< Reference count - - destroy_cb_fn on_destroy; ///< To remove any weak references - void *user_data; ///< User data for callbacks + REF_COUNTABLE_HEADER // TODO: eventually a reference to the server @@ -162,29 +189,13 @@ user_new (void) static void user_destroy (struct user *self) { - if (self->on_destroy) - self->on_destroy (self, self->user_data); - free (self->nickname); LIST_FOR_EACH (struct user_channel, iter, self->channels) user_channel_destroy (iter); free (self); } -static struct user * -user_ref (struct user *self) -{ - self->ref_count++; - return self; -} - -static void -user_unref (void *p) -{ - struct user *self = p; - if (!--self->ref_count) - user_destroy (self); -} +REF_COUNTABLE_METHODS (user) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -204,9 +215,8 @@ channel_user_new (void) } static void -channel_user_destroy (void *p) +channel_user_destroy (struct channel_user *self) { - struct channel_user *self = p; user_unref (self->user); free (self->modes); free (self); @@ -219,10 +229,7 @@ channel_user_destroy (void *p) struct channel { - size_t ref_count; ///< Reference count - - destroy_cb_fn on_destroy; ///< To remove any weak references - void *user_data; ///< User data for callbacks + REF_COUNTABLE_HEADER // TODO: eventually a reference to the server @@ -244,9 +251,6 @@ channel_new (void) static void channel_destroy (struct channel *self) { - if (self->on_destroy) - self->on_destroy (self, self->user_data); - free (self->name); free (self->mode); free (self->topic); @@ -255,20 +259,7 @@ channel_destroy (struct channel *self) free (self); } -static struct channel * -channel_ref (struct channel *self) -{ - self->ref_count++; - return self; -} - -static void -channel_unref (void *p) -{ - struct channel *self = p; - if (!--self->ref_count) - channel_destroy (self); -} +REF_COUNTABLE_METHODS (channel) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -