The implementation in this commit allows for one bit worth of flags.  If
more flags are desired at a future date, then the wl_map implementation
will have to change but the wl_map API will not.

Signed-off-by: Jason Ekstrand <ja...@jlekstrand.net>
---
 src/wayland-client.c  | 12 ++++++------
 src/wayland-private.h | 13 +++++++++++--
 src/wayland-server.c  | 12 ++++++------
 src/wayland-util.c    | 41 +++++++++++++++++++++++++++++++++++------
 4 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index 0f5e093..bea73e0 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -226,7 +226,7 @@ wl_proxy_create(struct wl_proxy *factory, const struct 
wl_interface *interface)
        proxy->refcount = 1;
 
        pthread_mutex_lock(&display->mutex);
-       proxy->object.id = wl_map_insert_new(&display->objects, proxy);
+       proxy->object.id = wl_map_insert_new(&display->objects, 0, proxy);
        pthread_mutex_unlock(&display->mutex);
 
        return proxy;
@@ -252,7 +252,7 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
        proxy->flags = 0;
        proxy->refcount = 1;
 
-       wl_map_insert_at(&display->objects, id, proxy);
+       wl_map_insert_at(&display->objects, 0, id, proxy);
 
        return proxy;
 }
@@ -273,10 +273,10 @@ wl_proxy_destroy(struct wl_proxy *proxy)
        if (proxy->flags & WL_PROXY_FLAG_ID_DELETED)
                wl_map_remove(&proxy->display->objects, proxy->object.id);
        else if (proxy->object.id < WL_SERVER_ID_START)
-               wl_map_insert_at(&proxy->display->objects,
+               wl_map_insert_at(&proxy->display->objects, 0,
                                 proxy->object.id, WL_ZOMBIE_OBJECT);
        else
-               wl_map_insert_at(&proxy->display->objects,
+               wl_map_insert_at(&proxy->display->objects, 0,
                                 proxy->object.id, NULL);
 
 
@@ -522,11 +522,11 @@ wl_display_connect_to_fd(int fd)
        wl_list_init(&display->event_queue_list);
        pthread_mutex_init(&display->mutex, NULL);
 
-       wl_map_insert_new(&display->objects, NULL);
+       wl_map_insert_new(&display->objects, 0, NULL);
 
        display->proxy.object.interface = &wl_display_interface;
        display->proxy.object.id =
-               wl_map_insert_new(&display->objects, display);
+               wl_map_insert_new(&display->objects, 0, display);
        display->proxy.display = display;
        display->proxy.object.implementation = (void(**)(void)) 
&display_listener;
        display->proxy.user_data = display;
diff --git a/src/wayland-private.h b/src/wayland-private.h
index 270b470..a648538 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -41,6 +41,14 @@
 #define WL_SERVER_ID_START 0xff000000
 #define WL_CLOSURE_MAX_ARGS 20
 
+/* Flags for wl_map_insert_new and wl_map_insert_at.  Flags can be queried with
+ * wl_map_lookup_flags.  The current implementation has room for 1 bit worth of
+ * flags.  If more flags are ever added, the implementation of wl_map will have
+ * to change to allow for new flags */
+enum wl_map_entry_flags {
+       WL_MAP_ENTRY_LEGACY = (1 << 0)
+};
+
 struct wl_map {
        struct wl_array client_entries;
        struct wl_array server_entries;
@@ -52,11 +60,12 @@ typedef void (*wl_iterator_func_t)(void *element, void 
*data);
 
 void wl_map_init(struct wl_map *map, uint32_t side);
 void wl_map_release(struct wl_map *map);
-uint32_t wl_map_insert_new(struct wl_map *map, void *data);
-int wl_map_insert_at(struct wl_map *map, uint32_t i, void *data);
+uint32_t wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data);
+int wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void 
*data);
 int wl_map_reserve_new(struct wl_map *map, uint32_t i);
 void wl_map_remove(struct wl_map *map, uint32_t i);
 void *wl_map_lookup(struct wl_map *map, uint32_t i);
+uint32_t wl_map_lookup_flags(struct wl_map *map, uint32_t i);
 void wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data);
 
 struct wl_connection;
diff --git a/src/wayland-server.c b/src/wayland-server.c
index c96be56..2d13d9d 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -338,7 +338,7 @@ wl_client_create(struct wl_display *display, int fd)
 
        wl_map_init(&client->objects, WL_MAP_SERVER_SIDE);
 
-       if (wl_map_insert_at(&client->objects, 0, NULL) < 0)
+       if (wl_map_insert_at(&client->objects, 0, 0, NULL) < 0)
                goto err_map;
 
        wl_signal_init(&client->destroy_signal);
@@ -379,8 +379,8 @@ wl_client_add_resource(struct wl_client *client,
 {
        if (resource->object.id == 0) {
                resource->object.id =
-                       wl_map_insert_new(&client->objects, resource);
-       } else if (wl_map_insert_at(&client->objects,
+                       wl_map_insert_new(&client->objects, 0, resource);
+       } else if (wl_map_insert_at(&client->objects, 0,
                                  resource->object.id, resource) < 0) {
                wl_resource_post_error(client->display_resource,
                                       WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -433,7 +433,7 @@ wl_resource_destroy(struct wl_resource *resource)
                        wl_resource_queue_event(client->display_resource,
                                                WL_DISPLAY_DELETE_ID, id);
                }
-               wl_map_insert_at(&client->objects, id, NULL);
+               wl_map_insert_at(&client->objects, 0, id, NULL);
        } else {
                wl_map_remove(&client->objects, id);
        }
@@ -912,7 +912,7 @@ wl_client_add_object(struct wl_client *client,
        resource->client = client;
        resource->destroy = (void *) free;
 
-       if (wl_map_insert_at(&client->objects, resource->object.id, resource) < 
0) {
+       if (wl_map_insert_at(&client->objects, 0, resource->object.id, 
resource) < 0) {
                wl_resource_post_error(client->display_resource,
                                       WL_DISPLAY_ERROR_INVALID_OBJECT,
                                       "invalid new id %d",
@@ -931,7 +931,7 @@ wl_client_new_object(struct wl_client *client,
 {
        uint32_t id;
 
-       id = wl_map_insert_new(&client->objects, NULL);
+       id = wl_map_insert_new(&client->objects, 0, NULL);
        return wl_client_add_object(client,
                                    interface, implementation, id, data);
 
diff --git a/src/wayland-util.c b/src/wayland-util.c
index 57f496b..162b352 100644
--- a/src/wayland-util.c
+++ b/src/wayland-util.c
@@ -151,6 +151,10 @@ union map_entry {
        void *data;
 };
 
+#define map_entry_is_free(entry) ((entry).next & 0x1)
+#define map_entry_get_data(entry) ((void *)((entry).next & ~(uintptr_t)0x3))
+#define map_entry_get_flags(entry) (((entry).next >> 1) & 0x1)
+
 WL_EXPORT void
 wl_map_init(struct wl_map *map, uint32_t side)
 {
@@ -166,7 +170,7 @@ wl_map_release(struct wl_map *map)
 }
 
 WL_EXPORT uint32_t
-wl_map_insert_new(struct wl_map *map, void *data)
+wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data)
 {
        union map_entry *start, *entry;
        struct wl_array *entries;
@@ -192,12 +196,13 @@ wl_map_insert_new(struct wl_map *map, void *data)
        }
 
        entry->data = data;
+       entry->next |= (flags & 0x1) << 1;
 
        return (entry - start) + base;
 }
 
 WL_EXPORT int
-wl_map_insert_at(struct wl_map *map, uint32_t i, void *data)
+wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data)
 {
        union map_entry *start;
        uint32_t count;
@@ -225,6 +230,7 @@ wl_map_insert_at(struct wl_map *map, uint32_t i, void *data)
 
        start = entries->data;
        start[i].data = data;
+       start[i].next |= (flags & 0x1) << 1;
 
        return 0;
 }
@@ -309,12 +315,35 @@ wl_map_lookup(struct wl_map *map, uint32_t i)
        start = entries->data;
        count = entries->size / sizeof *start;
 
-       if (i < count && !(start[i].next & 1))
-               return start[i].data;
+       if (i < count && !map_entry_is_free(start[i]))
+               return map_entry_get_data(start[i]);
 
        return NULL;
 }
 
+WL_EXPORT uint32_t
+wl_map_lookup_flags(struct wl_map *map, uint32_t i)
+{
+       union map_entry *start;
+       uint32_t count;
+       struct wl_array *entries;
+
+       if (i < WL_SERVER_ID_START) {
+               entries = &map->client_entries;
+       } else {
+               entries = &map->server_entries;
+               i -= WL_SERVER_ID_START;
+       }
+
+       start = entries->data;
+       count = entries->size / sizeof *start;
+
+       if (i < count && !map_entry_is_free(start[i]))
+               return map_entry_get_flags(start[i]);
+
+       return 0;
+}
+
 static void
 for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
 {
@@ -324,8 +353,8 @@ for_each_helper(struct wl_array *entries, 
wl_iterator_func_t func, void *data)
        end = (union map_entry *) ((char *) entries->data + entries->size);
 
        for (p = start; p < end; p++)
-               if (p->data && !(p->next & 1))
-                       func(p->data, data);
+               if (p->data && !map_entry_is_free(*p))
+                       func(map_entry_get_data(*p), data);
 }
 
 WL_EXPORT void
-- 
1.8.1.4

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to