mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-03 09:01:42 -05:00
Add support for server allocated object IDs
We set aside a range of the object ID space for use by the server. This allows the server to bind an object to an ID for a client and pass that object to the client. The client can use the object immediately and the server can emit events to the object immdiately.
This commit is contained in:
parent
190492b97c
commit
bdbd6ef80b
5 changed files with 108 additions and 30 deletions
|
|
@ -132,7 +132,27 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
|
||||||
|
|
||||||
proxy->object.interface = interface;
|
proxy->object.interface = interface;
|
||||||
proxy->object.implementation = NULL;
|
proxy->object.implementation = NULL;
|
||||||
proxy->object.id = wl_map_insert_new(&display->objects, proxy);
|
proxy->object.id = wl_map_insert_new(&display->objects,
|
||||||
|
WL_MAP_CLIENT_SIDE, proxy);
|
||||||
|
proxy->display = display;
|
||||||
|
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT struct wl_proxy *
|
||||||
|
wl_proxy_create_for_id(struct wl_proxy *factory,
|
||||||
|
uint32_t id, const struct wl_interface *interface)
|
||||||
|
{
|
||||||
|
struct wl_proxy *proxy;
|
||||||
|
struct wl_display *display = factory->display;
|
||||||
|
|
||||||
|
proxy = malloc(sizeof *proxy);
|
||||||
|
if (proxy == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
proxy->object.interface = interface;
|
||||||
|
proxy->object.implementation = NULL;
|
||||||
|
proxy->object.id = wl_map_insert_at(&display->objects, id, proxy);
|
||||||
proxy->display = display;
|
proxy->display = display;
|
||||||
|
|
||||||
return proxy;
|
return proxy;
|
||||||
|
|
@ -141,8 +161,12 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
wl_proxy_destroy(struct wl_proxy *proxy)
|
wl_proxy_destroy(struct wl_proxy *proxy)
|
||||||
{
|
{
|
||||||
|
if (proxy->object.id < WL_SERVER_ID_START)
|
||||||
wl_map_insert_at(&proxy->display->objects,
|
wl_map_insert_at(&proxy->display->objects,
|
||||||
proxy->object.id, WL_ZOMBIE_OBJECT);
|
proxy->object.id, WL_ZOMBIE_OBJECT);
|
||||||
|
else
|
||||||
|
wl_map_insert_at(&proxy->display->objects,
|
||||||
|
proxy->object.id, NULL);
|
||||||
free(proxy);
|
free(proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,10 +360,12 @@ wl_display_connect(const char *name)
|
||||||
wl_list_init(&display->global_listener_list);
|
wl_list_init(&display->global_listener_list);
|
||||||
wl_list_init(&display->global_list);
|
wl_list_init(&display->global_list);
|
||||||
|
|
||||||
wl_map_insert_new(&display->objects, NULL);
|
wl_map_insert_new(&display->objects, WL_MAP_CLIENT_SIDE, NULL);
|
||||||
|
|
||||||
display->proxy.object.interface = &wl_display_interface;
|
display->proxy.object.interface = &wl_display_interface;
|
||||||
display->proxy.object.id = wl_map_insert_new(&display->objects, display);
|
display->proxy.object.id =
|
||||||
|
wl_map_insert_new(&display->objects,
|
||||||
|
WL_MAP_CLIENT_SIDE, 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;
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,10 @@ struct wl_display;
|
||||||
void wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);
|
void wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);
|
||||||
struct wl_proxy *wl_proxy_create(struct wl_proxy *factory,
|
struct wl_proxy *wl_proxy_create(struct wl_proxy *factory,
|
||||||
const struct wl_interface *interface);
|
const struct wl_interface *interface);
|
||||||
struct wl_proxy *wl_proxy_create_for_id(struct wl_display *display,
|
struct wl_proxy *wl_proxy_create_for_id(struct wl_proxy *factory,
|
||||||
const struct wl_interface *interface,
|
uint32_t id,
|
||||||
uint32_t id);
|
const struct wl_interface *interface);
|
||||||
|
|
||||||
void wl_proxy_destroy(struct wl_proxy *proxy);
|
void wl_proxy_destroy(struct wl_proxy *proxy);
|
||||||
int wl_proxy_add_listener(struct wl_proxy *proxy,
|
int wl_proxy_add_listener(struct wl_proxy *proxy,
|
||||||
void (**implementation)(void), void *data);
|
void (**implementation)(void), void *data);
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,19 @@
|
||||||
|
|
||||||
#define WL_ZOMBIE_OBJECT ((void *) 2)
|
#define WL_ZOMBIE_OBJECT ((void *) 2)
|
||||||
|
|
||||||
|
#define WL_MAP_SERVER_SIDE 0
|
||||||
|
#define WL_MAP_CLIENT_SIDE 1
|
||||||
|
#define WL_SERVER_ID_START 0xff000000
|
||||||
|
|
||||||
struct wl_map {
|
struct wl_map {
|
||||||
struct wl_array entries;
|
struct wl_array client_entries;
|
||||||
|
struct wl_array server_entries;
|
||||||
uint32_t free_list;
|
uint32_t free_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
void wl_map_init(struct wl_map *map);
|
void wl_map_init(struct wl_map *map);
|
||||||
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 side, 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 i, void *data);
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -336,9 +336,15 @@ wl_resource_destroy(struct wl_resource *resource, uint32_t time)
|
||||||
{
|
{
|
||||||
struct wl_client *client = resource->client;
|
struct wl_client *client = resource->client;
|
||||||
|
|
||||||
|
if (resource->object.id < WL_SERVER_ID_START) {
|
||||||
wl_resource_queue_event(resource->client->display_resource,
|
wl_resource_queue_event(resource->client->display_resource,
|
||||||
WL_DISPLAY_DELETE_ID, resource->object.id);
|
WL_DISPLAY_DELETE_ID,
|
||||||
|
resource->object.id);
|
||||||
wl_map_insert_at(&client->objects, resource->object.id, NULL);
|
wl_map_insert_at(&client->objects, resource->object.id, NULL);
|
||||||
|
} else {
|
||||||
|
wl_map_remove(&client->objects, resource->object.id);
|
||||||
|
}
|
||||||
|
|
||||||
destroy_resource(resource, &time);
|
destroy_resource(resource, &time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -148,26 +148,37 @@ wl_map_init(struct wl_map *map)
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
wl_map_release(struct wl_map *map)
|
wl_map_release(struct wl_map *map)
|
||||||
{
|
{
|
||||||
wl_array_release(&map->entries);
|
wl_array_release(&map->client_entries);
|
||||||
|
wl_array_release(&map->server_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 side, void *data)
|
||||||
{
|
{
|
||||||
union map_entry *start, *entry;
|
union map_entry *start, *entry;
|
||||||
|
struct wl_array *entries;
|
||||||
|
uint32_t base;
|
||||||
|
|
||||||
|
if (side == WL_MAP_CLIENT_SIDE) {
|
||||||
|
entries = &map->client_entries;
|
||||||
|
base = 0;
|
||||||
|
} else {
|
||||||
|
entries = &map->server_entries;
|
||||||
|
base = WL_SERVER_ID_START;
|
||||||
|
}
|
||||||
|
|
||||||
if (map->free_list) {
|
if (map->free_list) {
|
||||||
start = map->entries.data;
|
start = entries->data;
|
||||||
entry = &start[map->free_list >> 1];
|
entry = &start[map->free_list >> 1];
|
||||||
map->free_list = entry->next;
|
map->free_list = entry->next;
|
||||||
} else {
|
} else {
|
||||||
entry = wl_array_add(&map->entries, sizeof *entry);
|
entry = wl_array_add(entries, sizeof *entry);
|
||||||
start = map->entries.data;
|
start = entries->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->data = data;
|
entry->data = data;
|
||||||
|
|
||||||
return entry - start;
|
return (entry - start) + base;
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT int
|
WL_EXPORT int
|
||||||
|
|
@ -175,17 +186,23 @@ wl_map_insert_at(struct wl_map *map, uint32_t i, void *data)
|
||||||
{
|
{
|
||||||
union map_entry *start;
|
union map_entry *start;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
|
struct wl_array *entries;
|
||||||
|
|
||||||
/* assert(map->free_list == NULL */
|
if (i < WL_SERVER_ID_START) {
|
||||||
count = map->entries.size / sizeof *start;
|
entries = &map->client_entries;
|
||||||
|
} else {
|
||||||
|
entries = &map->server_entries;
|
||||||
|
i -= WL_SERVER_ID_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = entries->size / sizeof *start;
|
||||||
if (count < i)
|
if (count < i)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (count == i)
|
if (count == i)
|
||||||
wl_array_add(&map->entries, sizeof *start);
|
wl_array_add(entries, sizeof *start);
|
||||||
|
|
||||||
start = map->entries.data;
|
start = entries->data;
|
||||||
start[i].data = data;
|
start[i].data = data;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -195,8 +212,16 @@ WL_EXPORT void
|
||||||
wl_map_remove(struct wl_map *map, uint32_t i)
|
wl_map_remove(struct wl_map *map, uint32_t i)
|
||||||
{
|
{
|
||||||
union map_entry *start;
|
union map_entry *start;
|
||||||
|
struct wl_array *entries;
|
||||||
|
|
||||||
start = map->entries.data;
|
if (i < WL_SERVER_ID_START) {
|
||||||
|
entries = &map->client_entries;
|
||||||
|
} else {
|
||||||
|
entries = &map->server_entries;
|
||||||
|
i -= WL_SERVER_ID_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = entries->data;
|
||||||
start[i].next = map->free_list;
|
start[i].next = map->free_list;
|
||||||
map->free_list = (i << 1) | 1;
|
map->free_list = (i << 1) | 1;
|
||||||
}
|
}
|
||||||
|
|
@ -206,9 +231,17 @@ wl_map_lookup(struct wl_map *map, uint32_t i)
|
||||||
{
|
{
|
||||||
union map_entry *start;
|
union map_entry *start;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
|
struct wl_array *entries;
|
||||||
|
|
||||||
start = map->entries.data;
|
if (i < WL_SERVER_ID_START) {
|
||||||
count = map->entries.size / sizeof *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 && !(start[i].next & 1))
|
if (i < count && !(start[i].next & 1))
|
||||||
return start[i].data;
|
return start[i].data;
|
||||||
|
|
@ -216,15 +249,22 @@ wl_map_lookup(struct wl_map *map, uint32_t i)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
static void
|
||||||
wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data)
|
for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
|
||||||
{
|
{
|
||||||
union map_entry *start, *end, *p;
|
union map_entry *start, *end, *p;
|
||||||
|
|
||||||
start = map->entries.data;
|
start = entries->data;
|
||||||
end = (union map_entry *) ((char *) map->entries.data + map->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 && !(p->next & 1))
|
||||||
func(p->data, data);
|
func(p->data, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue