From 5632eecd42a95976cfadb4a089ff5e62734cc743 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Tue, 21 Apr 2015 00:29:07 +0200
Subject: degesch: get rid of repeating refcounting code
Macros aren't exactly spectacular but they work.
---
degesch.c | 87 ++++++++++++++++++++++++++++-----------------------------------
1 file changed, 39 insertions(+), 48 deletions(-)
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)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
cgit v1.2.3-70-g09d2