Add API to retrieve and iterate over the resources list of a client
authorGiulio Camuffo <giuliocamuffo@gmail.com>
Thu, 11 Aug 2016 15:23:10 +0000 (17:23 +0200)
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>
Fri, 12 Aug 2016 08:53:16 +0000 (11:53 +0300)
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@kdab.com>
Reviewed-by: Jonas Ã…dahl <jadahl@gmail.com>
[Pekka: added empty lines, init ret in for_each_helper()]
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
src/wayland-private.h
src/wayland-server-core.h
src/wayland-server.c
src/wayland-util.c
src/wayland-util.h

index adfbe01..ac712d9 100644 (file)
@@ -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);
index bb0a989..56e8d80 100644 (file)
@@ -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
index a396410..dd648ac 100644 (file)
@@ -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,52 @@ 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.
+ *
+ * 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
index 7467366..639ccf8 100644 (file)
@@ -359,24 +359,33 @@ 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 = 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;
+
+       ret = for_each_helper(&map->client_entries, func, data);
+       if (ret == WL_ITERATOR_CONTINUE)
+               for_each_helper(&map->server_entries, func, data);
 }
 
 static void
index 8da156c..cacc122 100644 (file)
@@ -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