degesch: extend weak pointers

This commit is contained in:
Přemysl Eric Janouch 2015-11-18 23:03:21 +01:00
parent 89065e4d34
commit b952fc1f6d
1 changed files with 43 additions and 10 deletions

View File

@ -732,16 +732,29 @@ input_on_readable (struct input *self)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// We need a few reference countable objects with support
// for both strong and weak references
// We need a few reference countable objects with support for both strong
// and weak references (mainly used for scripted plugins).
//
// Beware that if you don't own the object, you will most probably want
// to keep the weak reference link so that you can get rid of it later.
// Also note that you have to make sure the user_data don't leak resources.
//
// Having a callback is more versatile than just nulling out a pointer.
/// Callback just before a reference counted object is destroyed
typedef void (*destroy_cb_fn) (void *object, void *user_data);
struct weak_ref_link
{
LIST_HEADER (struct weak_ref_link)
destroy_cb_fn on_destroy; ///< Called when object is destroyed
void *user_data; ///< 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 */
struct weak_ref_link *weak_refs; /**< To remove any weak references */
#define REF_COUNTABLE_METHODS(name) \
static struct name * \
@ -756,9 +769,31 @@ typedef void (*destroy_cb_fn) (void *object, void *user_data);
{ \
if (--self->ref_count) \
return; \
if (self->on_destroy) \
self->on_destroy (self, self->user_data); \
LIST_FOR_EACH (struct weak_ref_link, iter, self->weak_refs) \
{ \
iter->on_destroy (self, iter->user_data); \
free (iter); \
} \
name ## _destroy (self); \
} \
\
static struct weak_ref_link * \
name ## _weak_ref (struct name *self, destroy_cb_fn cb, void *user_data) \
{ \
struct weak_ref_link *link = xcalloc (1, sizeof *link); \
link->on_destroy = cb; \
link->user_data = user_data; \
LIST_PREPEND (self->weak_refs, link); \
return link; \
} \
\
static void \
name ## _weak_unref (struct name *self, struct weak_ref_link **link) \
{ \
if (*link) \
LIST_UNLINK (self->weak_refs, *link); \
free (*link); \
*link = NULL; \
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -3378,8 +3413,7 @@ irc_make_user (struct server *s, char *nickname)
hard_assert (!str_map_find (&s->irc_users, nickname));
struct user *user = user_new ();
user->on_destroy = irc_user_on_destroy;
user->user_data = s;
(void) user_weak_ref (user, irc_user_on_destroy, s);
user->nickname = nickname;
str_map_set (&s->irc_users, user->nickname, user);
return user;
@ -3482,8 +3516,7 @@ irc_make_channel (struct server *s, char *name)
hard_assert (!str_map_find (&s->irc_channels, name));
struct channel *channel = channel_new ();
channel->on_destroy = irc_channel_on_destroy;
channel->user_data = s;
(void) channel_weak_ref (channel, irc_channel_on_destroy, s);
channel->name = name;
channel->topic = NULL;
str_map_set (&s->irc_channels, channel->name, channel);