[PATCH weston v3 5/6] Add API to retrieve and iterate over the resources list of a client

Pekka Paalanen ppaalanen at gmail.com
Thu Aug 11 14:34:43 UTC 2016


On Tue,  9 Aug 2016 12:46:55 +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>
> ---
> 
> v3: - add a new wl_iterator_enum to be used instead of the plain int as the
>       return type of the iterator to break the loop
> 
>  src/wayland-private.h     |  3 ++-
>  src/wayland-server-core.h |  9 +++++++++
>  src/wayland-server.c      | 49 ++++++++++++++++++++++++++++++++++++++++++++++-
>  src/wayland-util.c        |  8 ++++++--
>  src/wayland-util.h        | 11 +++++++++++
>  5 files changed, 76 insertions(+), 4 deletions(-)
> 
> 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 067d8a5..fb44f13 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
> @@ -1603,6 +1605,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;
> +	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.

Hi Giulio

Except it is not guaranteed that it will stop.

If you look at wl_map_for_each(), you see it iterates server and client
side created objects separately. Trying to stop during the firsts will
still iterate over the second.

Maybe stopping mid-iterating was not a good idea after all.

Otherwise the patch is good.

What do you want to do?

I'd be ok with just changing the wording in the documentation, but it
would also be acceptable to me to either not have it stoppable at all
like you had, or make it really stop guaranteed.


Thanks,
pq


> + *
> + * 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..3c38116 100644
> --- a/src/wayland-util.c
> +++ b/src/wayland-util.c
> @@ -363,13 +363,17 @@ static void
>  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;
>  
>  	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;
> +		}
>  }
>  
>  WL_EXPORT 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

-------------- 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/20160811/9c61aba2/attachment.sig>


More information about the wayland-devel mailing list