degesch: get rid of repeating refcounting code

Macros aren't exactly spectacular but they work.
This commit is contained in:
Přemysl Eric Janouch 2015-04-21 00:29:07 +02:00
parent 635c28820d
commit 5632eecd42
1 changed files with 39 additions and 48 deletions

View File

@ -100,12 +100,43 @@ static struct config_item g_config_table[] =
return false; \ return false; \
BLOCK_END BLOCK_END
static void user_unref (void *p); struct user;
static void channel_unref (void *p); 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 /// Callback just before a reference counted object is destroyed
typedef void (*destroy_cb_fn) (void *object, void *user_data); 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 struct user_channel
@ -123,9 +154,8 @@ user_channel_new (void)
} }
static void static void
user_channel_destroy (void *p) user_channel_destroy (struct user_channel *self)
{ {
struct user_channel *self = p;
channel_unref (self->channel); channel_unref (self->channel);
free (self); free (self);
} }
@ -137,10 +167,7 @@ user_channel_destroy (void *p)
struct user struct user
{ {
size_t ref_count; ///< Reference count REF_COUNTABLE_HEADER
destroy_cb_fn on_destroy; ///< To remove any weak references
void *user_data; ///< User data for callbacks
// TODO: eventually a reference to the server // TODO: eventually a reference to the server
@ -162,29 +189,13 @@ user_new (void)
static void static void
user_destroy (struct user *self) user_destroy (struct user *self)
{ {
if (self->on_destroy)
self->on_destroy (self, self->user_data);
free (self->nickname); free (self->nickname);
LIST_FOR_EACH (struct user_channel, iter, self->channels) LIST_FOR_EACH (struct user_channel, iter, self->channels)
user_channel_destroy (iter); user_channel_destroy (iter);
free (self); free (self);
} }
static struct user * REF_COUNTABLE_METHODS (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);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -204,9 +215,8 @@ channel_user_new (void)
} }
static void static void
channel_user_destroy (void *p) channel_user_destroy (struct channel_user *self)
{ {
struct channel_user *self = p;
user_unref (self->user); user_unref (self->user);
free (self->modes); free (self->modes);
free (self); free (self);
@ -219,10 +229,7 @@ channel_user_destroy (void *p)
struct channel struct channel
{ {
size_t ref_count; ///< Reference count REF_COUNTABLE_HEADER
destroy_cb_fn on_destroy; ///< To remove any weak references
void *user_data; ///< User data for callbacks
// TODO: eventually a reference to the server // TODO: eventually a reference to the server
@ -244,9 +251,6 @@ channel_new (void)
static void static void
channel_destroy (struct channel *self) channel_destroy (struct channel *self)
{ {
if (self->on_destroy)
self->on_destroy (self, self->user_data);
free (self->name); free (self->name);
free (self->mode); free (self->mode);
free (self->topic); free (self->topic);
@ -255,20 +259,7 @@ channel_destroy (struct channel *self)
free (self); free (self);
} }
static struct channel * REF_COUNTABLE_METHODS (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);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -