[PATCH] event-loop: Use two-step destruction of event loop sources.

Ander Conselvan de Oliveira conselvan2 at gmail.com
Tue Mar 20 06:39:49 PDT 2012


On 03/20/2012 03:21 PM, Jonas Ådahl wrote:
> Instead of directly destroying an event source upon removal only destroy
> it in case its event loop is not dispatching. If dispatching the event
> source is marked for destruction and added to the check list and
> destroyed in post_dispatch_check(); if not it is destroyed immediately.
>
> Signed-off-by: Jonas Ådahl<jadahl at gmail.com>

Looks good me. Though maybe we want a wl_event_source_init() function to 
reduce the duplicated code from wl_event_loop_add* and avoid the 
calloc()'s. That also could go in another patch. Either way,

Reviewed-by: Ander Conselvan de Oliveira <conselvan2 at gmail.com>

> ---
>   src/event-loop.c |   73 ++++++++++++++++++++++++++++++++++-------------------
>   1 files changed, 47 insertions(+), 26 deletions(-)
>
> diff --git a/src/event-loop.c b/src/event-loop.c
> index 2dfe0ae..7f2ef80 100644
> --- a/src/event-loop.c
> +++ b/src/event-loop.c
> @@ -39,12 +39,15 @@ struct wl_event_loop {
>   	int epoll_fd;
>   	struct wl_list check_list;
>   	struct wl_list idle_list;
> +
> +	int dispatching;
>   };
>
>   struct wl_event_source_interface {
>   	int (*dispatch)(struct wl_event_source *source,
>   			struct epoll_event *ep);
>   	int (*remove)(struct wl_event_source *source);
> +	int (*destroy)(struct wl_event_source *source);
>   };
>
>   struct wl_event_source {
> @@ -52,6 +55,7 @@ struct wl_event_source {
>   	struct wl_event_loop *loop;
>   	struct wl_list link;
>   	void *data;
> +	int destroy;
>   };
>
>   struct wl_event_source_fd {
> @@ -61,6 +65,13 @@ struct wl_event_source_fd {
>   };
>
>   static int
> +wl_event_source_generic_destroy(struct wl_event_source *source)
> +{
> +	free(source);
> +	return 0;
> +}
> +
> +static int
>   wl_event_source_fd_dispatch(struct wl_event_source *source,
>   			    struct epoll_event *ep)
>   {
> @@ -82,17 +93,14 @@ wl_event_source_fd_remove(struct wl_event_source *source)
>   	struct wl_event_source_fd *fd_source =
>   		(struct wl_event_source_fd *) source;
>   	struct wl_event_loop *loop = source->loop;
> -	int fd;
> -
> -	fd = fd_source->fd;
> -	free(source);
>
> -	return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
> +	return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd_source->fd, NULL);
>   }
>
>   struct wl_event_source_interface fd_source_interface = {
>   	wl_event_source_fd_dispatch,
> -	wl_event_source_fd_remove
> +	wl_event_source_fd_remove,
> +	wl_event_source_generic_destroy
>   };
>
>   WL_EXPORT struct wl_event_source *
> @@ -104,7 +112,7 @@ wl_event_loop_add_fd(struct wl_event_loop *loop,
>   	struct wl_event_source_fd *source;
>   	struct epoll_event ep;
>
> -	source = malloc(sizeof *source);
> +	source = calloc(1, sizeof *source);
>   	if (source == NULL)
>   		return NULL;
>
> @@ -179,13 +187,13 @@ wl_event_source_timer_remove(struct wl_event_source *source)
>   		(struct wl_event_source_timer *) source;
>
>   	close(timer_source->fd);
> -	free(source);
>   	return 0;
>   }
>
>   struct wl_event_source_interface timer_source_interface = {
>   	wl_event_source_timer_dispatch,
> -	wl_event_source_timer_remove
> +	wl_event_source_timer_remove,
> +	wl_event_source_generic_destroy
>   };
>
>   WL_EXPORT struct wl_event_source *
> @@ -196,7 +204,7 @@ wl_event_loop_add_timer(struct wl_event_loop *loop,
>   	struct wl_event_source_timer *source;
>   	struct epoll_event ep;
>
> -	source = malloc(sizeof *source);
> +	source = calloc(1, sizeof *source);
>   	if (source == NULL)
>   		return NULL;
>
> @@ -278,13 +286,13 @@ wl_event_source_signal_remove(struct wl_event_source *source)
>   		(struct wl_event_source_signal *) source;
>
>   	close(signal_source->fd);
> -	free(source);
>   	return 0;
>   }
>
>   struct wl_event_source_interface signal_source_interface = {
>   	wl_event_source_signal_dispatch,
> -	wl_event_source_signal_remove
> +	wl_event_source_signal_remove,
> +	wl_event_source_generic_destroy
>   };
>
>   WL_EXPORT struct wl_event_source *
> @@ -297,7 +305,7 @@ wl_event_loop_add_signal(struct wl_event_loop *loop,
>   	struct epoll_event ep;
>   	sigset_t mask;
>
> -	source = malloc(sizeof *source);
> +	source = calloc(1, sizeof *source);
>   	if (source == NULL)
>   		return NULL;
>
> @@ -337,17 +345,10 @@ struct wl_event_source_idle {
>   	wl_event_loop_idle_func_t func;
>   };
>
> -static int
> -wl_event_source_idle_remove(struct wl_event_source *source)
> -{
> -	free(source);
> -
> -	return 0;
> -}
> -
>   struct wl_event_source_interface idle_source_interface = {
>   	NULL,
> -	wl_event_source_idle_remove
> +	NULL,
> +	wl_event_source_generic_destroy
>   };
>
>   WL_EXPORT struct wl_event_source *
> @@ -357,7 +358,7 @@ wl_event_loop_add_idle(struct wl_event_loop *loop,
>   {
>   	struct wl_event_source_idle *source;
>
> -	source = malloc(sizeof *source);
> +	source = calloc(1, sizeof *source);
>   	if (source == NULL)
>   		return NULL;
>
> @@ -381,11 +382,22 @@ wl_event_source_check(struct wl_event_source *source)
>   WL_EXPORT int
>   wl_event_source_remove(struct wl_event_source *source)
>   {
> +	struct wl_event_loop *loop = source->loop;
> +
>   	if (!wl_list_empty(&source->link))
>   		wl_list_remove(&source->link);
>
>   	source->interface->remove(source);
>
> +	if (loop->dispatching) {
> +		source->destroy = 1;
> +
> +		if (!wl_list_empty(&source->link))
> +			wl_list_remove(&source->link);
> +		wl_event_source_check(source);
> +	} else
> +		source->interface->destroy(source);
> +
>   	return 0;
>   }
>
> @@ -425,8 +437,13 @@ post_dispatch_check(struct wl_event_loop *loop)
>
>   	ep.events = 0;
>   	n = 0;
> -	wl_list_for_each_safe(source, next,&loop->check_list, link)
> -		n += source->interface->dispatch(source,&ep);
> +	wl_list_for_each_safe(source, next,&loop->check_list, link) {
> +		if (source->destroy) {
> +			wl_list_remove(&source->link);
> +			source->interface->destroy(source);
> +		} else
> +			n += source->interface->dispatch(source,&ep);
> +	}
>
>   	return n;
>   }
> @@ -456,11 +473,15 @@ wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
>   	count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
>   	if (count<  0)
>   		return -1;
> +
> +	loop->dispatching = 1;
>   	n = 0;
>   	for (i = 0; i<  count; i++) {
>   		source = ep[i].data.ptr;
> -		n += source->interface->dispatch(source,&ep[i]);
> +		if (!source->destroy)
> +			n += source->interface->dispatch(source,&ep[i]);
>   	}
> +	loop->dispatching = 0;
>
>   	while (n>  0)
>   		n = post_dispatch_check(loop);



More information about the wayland-devel mailing list