[PATCH wayland v4 2/3] Add API to retrieve and iterate over the resources list of a client

Pekka Paalanen ppaalanen at gmail.com
Fri Aug 12 08:56:02 UTC 2016


On Thu, 11 Aug 2016 17:23:10 +0200
Giulio Camuffo <giuliocamuffo at gmail.com> wrote:

> To complement on the new resource created signal, this allows to
> iterate over the existing resources of a client.
> 
> Signed-off-by: Giulio Camuffo <giulio.camuffo at kdab.com>
> Reviewed-by: Jonas Ã…dahl <jadahl at gmail.com>
> ---
> 
> v4: - really stop when the iterator says so
> 
>  src/wayland-private.h     |  3 ++-
>  src/wayland-server-core.h |  9 +++++++++
>  src/wayland-server.c      | 49 ++++++++++++++++++++++++++++++++++++++++++++++-
>  src/wayland-util.c        | 18 ++++++++++++-----
>  src/wayland-util.h        | 11 +++++++++++
>  5 files changed, 83 insertions(+), 7 deletions(-)

Hi Giulio,

patches 1 and 2 pushed:
   596024f..2f61725  master -> master


But I did do some minor changes.

In patch 1, I added:
+	/* This is defined to be safe also after client destruction */
+	wl_list_remove(&resource_listener.listener.link);

in the test so that we also remove the listener at some point.

In patch 2, see below.

> 
> diff --git a/src/wayland-private.h b/src/wayland-private.h
> index adfbe01..ac712d9 100644
> --- a/src/wayland-private.h
> +++ b/src/wayland-private.h
> @@ -75,7 +75,8 @@ struct wl_map {
>  	uint32_t free_list;
>  };
>  
> -typedef void (*wl_iterator_func_t)(void *element, void *data);
> +typedef enum wl_iterator_result (*wl_iterator_func_t)(void *element,
> +						      void *data);
>  
>  void
>  wl_map_init(struct wl_map *map, uint32_t side);
> diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h
> index bb0a989..56e8d80 100644
> --- a/src/wayland-server-core.h
> +++ b/src/wayland-server-core.h
> @@ -216,6 +216,15 @@ void
>  wl_client_add_resource_created_listener(struct wl_client *client,
>                                          struct wl_listener *listener);
>  
> +typedef enum wl_iterator_result (*wl_client_for_each_resource_iterator_func_t)(
> +						struct wl_resource *resource,
> +						void *user_data);
> +
> +void
> +wl_client_for_each_resource(struct wl_client *client,
> +                            wl_client_for_each_resource_iterator_func_t iterator,
> +                            void *user_data);
> +
>  /** \class wl_listener
>   *
>   * \brief A single listener for Wayland signals
> diff --git a/src/wayland-server.c b/src/wayland-server.c
> index a396410..c53a2f4 100644
> --- a/src/wayland-server.c
> +++ b/src/wayland-server.c
> @@ -565,7 +565,7 @@ wl_resource_post_no_memory(struct wl_resource *resource)
>  			       WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
>  }
>  
> -static void
> +static enum wl_iterator_result
>  destroy_resource(void *element, void *data)
>  {
>  	struct wl_resource *resource = element;
> @@ -580,6 +580,8 @@ destroy_resource(void *element, void *data)
>  
>  	if (!(flags & WL_MAP_ENTRY_LEGACY))
>  		free(resource);
> +
> +	return WL_ITERATOR_CONTINUE;
>  }
>  
>  WL_EXPORT void
> @@ -1604,6 +1606,51 @@ wl_client_add_resource_created_listener(struct wl_client *client,
>  	wl_signal_add(&client->resource_created_signal, listener);
>  }
>  
> +struct wl_resource_iterator_context {
> +	void *user_data;
> +	wl_client_for_each_resource_iterator_func_t it;
> +};
> +
> +static enum wl_iterator_result
> +resource_iterator_helper(void *res, void *user_data)
> +{
> +	struct wl_resource_iterator_context *context = user_data;
> +	struct wl_resource *resource = res;

Added newline.

> +	return context->it(resource, context->user_data);
> +}
> +
> +/** Iterate over all the resources of a client
> + *
> + * \param client The client object
> + * \param iterator The iterator function
> + * \param user_data The user data pointer
> + *
> + * The function pointed by \a iterator will be called for each
> + * resource owned by the client. The \a user_data will be passed
> + * as the second argument of the iterator function.
> + * If the \a iterator function returns \a WL_ITERATOR_CONTINUE the iteration
> + * will continue, if it returns \a WL_ITERATOR_STOP it will stop.
> + *
> + * Creating and destroying resources while iterating is safe, but new
> + * resources may or may not be picked up by the iterator.
> + *
> + * \sa wl_iterator_result
> + *
> + * \memberof wl_client
> + */
> +WL_EXPORT void
> +wl_client_for_each_resource(struct wl_client *client,
> +			    wl_client_for_each_resource_iterator_func_t iterator,
> +			    void *user_data)
> +{
> +	struct wl_resource_iterator_context context = {
> +		.user_data = user_data,
> +		.it = iterator,
> +	};
> +
> +	wl_map_for_each(&client->objects, resource_iterator_helper, &context);
> +}
> +
>  /** \cond */ /* Deprecated functions below. */
>  
>  uint32_t
> diff --git a/src/wayland-util.c b/src/wayland-util.c
> index 7467366..43aab83 100644
> --- a/src/wayland-util.c
> +++ b/src/wayland-util.c
> @@ -359,24 +359,32 @@ wl_map_lookup_flags(struct wl_map *map, uint32_t i)
>  	return 0;
>  }
>  
> -static void
> +static enum wl_iterator_result
>  for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
>  {
>  	union map_entry *start, *end, *p;
> +	enum wl_iterator_result ret;

'ret' is used uninitialized if the array is empty; added initialization
to WL_ITERATOR_CONTINUE.


>  
>  	start = entries->data;
>  	end = (union map_entry *) ((char *) entries->data + entries->size);
>  
>  	for (p = start; p < end; p++)
> -		if (p->data && !map_entry_is_free(*p))
> -			func(map_entry_get_data(*p), data);
> +		if (p->data && !map_entry_is_free(*p)) {
> +			ret = func(map_entry_get_data(*p), data);
> +			if (ret != WL_ITERATOR_CONTINUE)
> +				break;
> +		}
> +
> +	return ret;
>  }
>  
>  WL_EXPORT void
>  wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data)
>  {
> -	for_each_helper(&map->client_entries, func, data);
> -	for_each_helper(&map->server_entries, func, data);
> +	enum wl_iterator_result ret;

Added newline.

> +	ret = for_each_helper(&map->client_entries, func, data);
> +	if (ret == WL_ITERATOR_CONTINUE)
> +		for_each_helper(&map->server_entries, func, data);
>  }
>  
>  static void
> diff --git a/src/wayland-util.h b/src/wayland-util.h
> index 8da156c..cacc122 100644
> --- a/src/wayland-util.h
> +++ b/src/wayland-util.h
> @@ -311,6 +311,17 @@ typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t,
>  
>  typedef void (*wl_log_func_t)(const char *, va_list) WL_PRINTF(1, 0);
>  
> +/** \enum wl_iterator_result
> + *
> + * This enum represents the return value of an iterator function.
> + */
> +enum wl_iterator_result {
> +	/** Stop the iteration */
> +	WL_ITERATOR_STOP,
> +	/** Continue the iteration */
> +	WL_ITERATOR_CONTINUE
> +};
> +
>  #ifdef  __cplusplus
>  }
>  #endif


Thanks,
pq
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 811 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20160812/18b14571/attachment.sig>


More information about the wayland-devel mailing list