mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	Add support for flags in the wl_map API and add a WL_MAP_ENTRY_LEGACY flag
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 <jason@jlekstrand.net>
This commit is contained in:
		
							parent
							
								
									28472970df
								
							
						
					
					
						commit
						2c7468b868
					
				
					 4 changed files with 58 additions and 20 deletions
				
			
		| 
						 | 
					@ -226,7 +226,7 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
 | 
				
			||||||
	proxy->refcount = 1;
 | 
						proxy->refcount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pthread_mutex_lock(&display->mutex);
 | 
						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);
 | 
						pthread_mutex_unlock(&display->mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return proxy;
 | 
						return proxy;
 | 
				
			||||||
| 
						 | 
					@ -252,7 +252,7 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
 | 
				
			||||||
	proxy->flags = 0;
 | 
						proxy->flags = 0;
 | 
				
			||||||
	proxy->refcount = 1;
 | 
						proxy->refcount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_map_insert_at(&display->objects, id, proxy);
 | 
						wl_map_insert_at(&display->objects, 0, id, proxy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return proxy;
 | 
						return proxy;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -273,10 +273,10 @@ wl_proxy_destroy(struct wl_proxy *proxy)
 | 
				
			||||||
	if (proxy->flags & WL_PROXY_FLAG_ID_DELETED)
 | 
						if (proxy->flags & WL_PROXY_FLAG_ID_DELETED)
 | 
				
			||||||
		wl_map_remove(&proxy->display->objects, proxy->object.id);
 | 
							wl_map_remove(&proxy->display->objects, proxy->object.id);
 | 
				
			||||||
	else if (proxy->object.id < WL_SERVER_ID_START)
 | 
						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);
 | 
									 proxy->object.id, WL_ZOMBIE_OBJECT);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		wl_map_insert_at(&proxy->display->objects,
 | 
							wl_map_insert_at(&proxy->display->objects, 0,
 | 
				
			||||||
				 proxy->object.id, NULL);
 | 
									 proxy->object.id, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -522,11 +522,11 @@ wl_display_connect_to_fd(int fd)
 | 
				
			||||||
	wl_list_init(&display->event_queue_list);
 | 
						wl_list_init(&display->event_queue_list);
 | 
				
			||||||
	pthread_mutex_init(&display->mutex, NULL);
 | 
						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.interface = &wl_display_interface;
 | 
				
			||||||
	display->proxy.object.id =
 | 
						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.display = display;
 | 
				
			||||||
	display->proxy.object.implementation = (void(**)(void)) &display_listener;
 | 
						display->proxy.object.implementation = (void(**)(void)) &display_listener;
 | 
				
			||||||
	display->proxy.user_data = display;
 | 
						display->proxy.user_data = display;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,14 @@
 | 
				
			||||||
#define WL_SERVER_ID_START 0xff000000
 | 
					#define WL_SERVER_ID_START 0xff000000
 | 
				
			||||||
#define WL_CLOSURE_MAX_ARGS 20
 | 
					#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_map {
 | 
				
			||||||
	struct wl_array client_entries;
 | 
						struct wl_array client_entries;
 | 
				
			||||||
	struct wl_array server_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_init(struct wl_map *map, uint32_t side);
 | 
				
			||||||
void wl_map_release(struct wl_map *map);
 | 
					void wl_map_release(struct wl_map *map);
 | 
				
			||||||
uint32_t wl_map_insert_new(struct wl_map *map, 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 i, 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);
 | 
					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_remove(struct wl_map *map, uint32_t i);
 | 
				
			||||||
void *wl_map_lookup(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);
 | 
					void wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_connection;
 | 
					struct wl_connection;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -338,7 +338,7 @@ wl_client_create(struct wl_display *display, int fd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_map_init(&client->objects, WL_MAP_SERVER_SIDE);
 | 
						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;
 | 
							goto err_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_signal_init(&client->destroy_signal);
 | 
						wl_signal_init(&client->destroy_signal);
 | 
				
			||||||
| 
						 | 
					@ -379,8 +379,8 @@ wl_client_add_resource(struct wl_client *client,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (resource->object.id == 0) {
 | 
						if (resource->object.id == 0) {
 | 
				
			||||||
		resource->object.id =
 | 
							resource->object.id =
 | 
				
			||||||
			wl_map_insert_new(&client->objects, resource);
 | 
								wl_map_insert_new(&client->objects, 0, resource);
 | 
				
			||||||
	} else if (wl_map_insert_at(&client->objects,
 | 
						} else if (wl_map_insert_at(&client->objects, 0,
 | 
				
			||||||
				  resource->object.id, resource) < 0) {
 | 
									  resource->object.id, resource) < 0) {
 | 
				
			||||||
		wl_resource_post_error(client->display_resource,
 | 
							wl_resource_post_error(client->display_resource,
 | 
				
			||||||
				       WL_DISPLAY_ERROR_INVALID_OBJECT,
 | 
									       WL_DISPLAY_ERROR_INVALID_OBJECT,
 | 
				
			||||||
| 
						 | 
					@ -433,7 +433,7 @@ wl_resource_destroy(struct wl_resource *resource)
 | 
				
			||||||
			wl_resource_queue_event(client->display_resource,
 | 
								wl_resource_queue_event(client->display_resource,
 | 
				
			||||||
						WL_DISPLAY_DELETE_ID, id);
 | 
											WL_DISPLAY_DELETE_ID, id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		wl_map_insert_at(&client->objects, id, NULL);
 | 
							wl_map_insert_at(&client->objects, 0, id, NULL);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		wl_map_remove(&client->objects, id);
 | 
							wl_map_remove(&client->objects, id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -912,7 +912,7 @@ wl_client_add_object(struct wl_client *client,
 | 
				
			||||||
	resource->client = client;
 | 
						resource->client = client;
 | 
				
			||||||
	resource->destroy = (void *) free;
 | 
						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_resource_post_error(client->display_resource,
 | 
				
			||||||
				       WL_DISPLAY_ERROR_INVALID_OBJECT,
 | 
									       WL_DISPLAY_ERROR_INVALID_OBJECT,
 | 
				
			||||||
				       "invalid new id %d",
 | 
									       "invalid new id %d",
 | 
				
			||||||
| 
						 | 
					@ -931,7 +931,7 @@ wl_client_new_object(struct wl_client *client,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t id;
 | 
						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,
 | 
						return wl_client_add_object(client,
 | 
				
			||||||
				    interface, implementation, id, data);
 | 
									    interface, implementation, id, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,6 +151,10 @@ union map_entry {
 | 
				
			||||||
	void *data;
 | 
						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_EXPORT void
 | 
				
			||||||
wl_map_init(struct wl_map *map, uint32_t side)
 | 
					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_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;
 | 
						union map_entry *start, *entry;
 | 
				
			||||||
	struct wl_array *entries;
 | 
						struct wl_array *entries;
 | 
				
			||||||
| 
						 | 
					@ -192,12 +196,13 @@ wl_map_insert_new(struct wl_map *map, void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	entry->data = data;
 | 
						entry->data = data;
 | 
				
			||||||
 | 
						entry->next |= (flags & 0x1) << 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (entry - start) + base;
 | 
						return (entry - start) + base;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT int
 | 
					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;
 | 
						union map_entry *start;
 | 
				
			||||||
	uint32_t count;
 | 
						uint32_t count;
 | 
				
			||||||
| 
						 | 
					@ -225,6 +230,7 @@ wl_map_insert_at(struct wl_map *map, uint32_t i, void *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	start = entries->data;
 | 
						start = entries->data;
 | 
				
			||||||
	start[i].data = data;
 | 
						start[i].data = data;
 | 
				
			||||||
 | 
						start[i].next |= (flags & 0x1) << 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -309,12 +315,35 @@ wl_map_lookup(struct wl_map *map, uint32_t i)
 | 
				
			||||||
	start = entries->data;
 | 
						start = entries->data;
 | 
				
			||||||
	count = entries->size / sizeof *start;
 | 
						count = entries->size / sizeof *start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < count && !(start[i].next & 1))
 | 
						if (i < count && !map_entry_is_free(start[i]))
 | 
				
			||||||
		return start[i].data;
 | 
							return map_entry_get_data(start[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return NULL;
 | 
						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
 | 
					static void
 | 
				
			||||||
for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
 | 
					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);
 | 
						end = (union map_entry *) ((char *) entries->data + entries->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (p = start; p < end; p++)
 | 
						for (p = start; p < end; p++)
 | 
				
			||||||
		if (p->data && !(p->next & 1))
 | 
							if (p->data && !map_entry_is_free(*p))
 | 
				
			||||||
			func(p->data, data);
 | 
								func(map_entry_get_data(*p), data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT void
 | 
					WL_EXPORT void
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue