diff options
Diffstat (limited to 'degesch.c')
| -rw-r--r-- | degesch.c | 53 | 
1 files changed, 43 insertions, 10 deletions
@@ -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);  | 
