mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-09 13:30:06 -05:00
global: avoid using existing global id
Add the global immediately after creating it. Make sure we only enumerate registered globals. This way, we can already check for duplicate ids before the global is registered. When allocating a global id, avoid using an existing id. Move some code around to make it easier to implement a more efficient algorithm for collision detection. Move the object id counter to the context.
This commit is contained in:
parent
3a49168f26
commit
5baab24848
3 changed files with 34 additions and 6 deletions
|
|
@ -570,6 +570,8 @@ int pw_context_for_each_global(struct pw_context *context,
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
spa_list_for_each_safe(g, t, &context->global_list, link) {
|
spa_list_for_each_safe(g, t, &context->global_list, link) {
|
||||||
|
if (!g->registered)
|
||||||
|
continue;
|
||||||
if (!global_can_read(context, g))
|
if (!global_can_read(context, g))
|
||||||
continue;
|
continue;
|
||||||
if ((res = callback(data, g)) != 0)
|
if ((res = callback(data, g)) != 0)
|
||||||
|
|
@ -588,12 +590,36 @@ static struct pw_global *find_global(struct pw_context *context, uint32_t id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t next_global_id(struct pw_context *context)
|
||||||
|
{
|
||||||
|
uint32_t id, retry = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
id = context->serial++ & 0xffffff;
|
||||||
|
if (find_global(context, id) == NULL)
|
||||||
|
return id;
|
||||||
|
if (retry++ > 4096)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return SPA_ID_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pw_context_add_global(struct pw_context *context, struct pw_global *global)
|
||||||
|
{
|
||||||
|
global->id = next_global_id(context);
|
||||||
|
spa_list_append(&context->global_list, &global->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pw_context_remove_global(struct pw_context *context, struct pw_global *global)
|
||||||
|
{
|
||||||
|
spa_list_remove(&global->link);
|
||||||
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
struct pw_global *pw_context_find_global(struct pw_context *context, uint32_t id)
|
struct pw_global *pw_context_find_global(struct pw_context *context, uint32_t id)
|
||||||
{
|
{
|
||||||
struct pw_global *global;
|
struct pw_global *global;
|
||||||
|
|
||||||
|
|
||||||
global = find_global(context, id);
|
global = find_global(context, id);
|
||||||
if (global == NULL || !global->registered) {
|
if (global == NULL || !global->registered) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,6 @@
|
||||||
PW_LOG_TOPIC_EXTERN(log_global);
|
PW_LOG_TOPIC_EXTERN(log_global);
|
||||||
#define PW_LOG_TOPIC_DEFAULT log_global
|
#define PW_LOG_TOPIC_DEFAULT log_global
|
||||||
|
|
||||||
static uint32_t serial = 0;
|
|
||||||
|
|
||||||
/** \cond */
|
/** \cond */
|
||||||
struct impl {
|
struct impl {
|
||||||
struct pw_global this;
|
struct pw_global this;
|
||||||
|
|
@ -96,11 +94,12 @@ pw_global_new(struct pw_context *context,
|
||||||
this->func = func;
|
this->func = func;
|
||||||
this->object = object;
|
this->object = object;
|
||||||
this->properties = properties;
|
this->properties = properties;
|
||||||
this->id = serial++ & 0xffffff;
|
|
||||||
|
|
||||||
spa_list_init(&this->resource_list);
|
spa_list_init(&this->resource_list);
|
||||||
spa_hook_list_init(&this->listener_list);
|
spa_hook_list_init(&this->listener_list);
|
||||||
|
|
||||||
|
pw_context_add_global(context, this);
|
||||||
|
|
||||||
pw_log_debug("%p: new %s %d", this, this->type, this->id);
|
pw_log_debug("%p: new %s %d", this, this->type, this->id);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -126,7 +125,6 @@ int pw_global_register(struct pw_global *global)
|
||||||
if (global->registered)
|
if (global->registered)
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
|
||||||
spa_list_append(&context->global_list, &global->link);
|
|
||||||
global->registered = true;
|
global->registered = true;
|
||||||
|
|
||||||
spa_list_for_each(registry, &context->registry_resource_list, link) {
|
spa_list_for_each(registry, &context->registry_resource_list, link) {
|
||||||
|
|
@ -163,7 +161,6 @@ static int global_unregister(struct pw_global *global)
|
||||||
pw_registry_resource_global_remove(resource, global->id);
|
pw_registry_resource_global_remove(resource, global->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_list_remove(&global->link);
|
|
||||||
global->registered = false;
|
global->registered = false;
|
||||||
|
|
||||||
pw_log_debug("%p: unregistered %u", global, global->id);
|
pw_log_debug("%p: unregistered %u", global, global->id);
|
||||||
|
|
@ -368,6 +365,7 @@ void pw_global_destroy(struct pw_global *global)
|
||||||
struct pw_resource *resource;
|
struct pw_resource *resource;
|
||||||
|
|
||||||
global->destroyed = true;
|
global->destroyed = true;
|
||||||
|
pw_context_remove_global(global->context, global);
|
||||||
|
|
||||||
pw_log_debug("%p: destroy %u", global, global->id);
|
pw_log_debug("%p: destroy %u", global, global->id);
|
||||||
pw_global_emit_destroy(global);
|
pw_global_emit_destroy(global);
|
||||||
|
|
|
||||||
|
|
@ -450,6 +450,7 @@ struct pw_context {
|
||||||
uint32_t n_support; /**< number of support items */
|
uint32_t n_support; /**< number of support items */
|
||||||
struct pw_array factory_lib; /**< mapping of factory_name regexp to library */
|
struct pw_array factory_lib; /**< mapping of factory_name regexp to library */
|
||||||
|
|
||||||
|
uint32_t serial;
|
||||||
struct pw_array objects; /**< objects */
|
struct pw_array objects; /**< objects */
|
||||||
|
|
||||||
struct pw_impl_client *current_client; /**< client currently executing code in mainloop */
|
struct pw_impl_client *current_client; /**< client currently executing code in mainloop */
|
||||||
|
|
@ -1115,6 +1116,9 @@ struct pw_control {
|
||||||
void *user_data;
|
void *user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t pw_context_add_global(struct pw_context *context, struct pw_global *global);
|
||||||
|
void pw_context_remove_global(struct pw_context *context, struct pw_global *global);
|
||||||
|
|
||||||
/** Find a good format between 2 ports */
|
/** Find a good format between 2 ports */
|
||||||
int pw_context_find_format(struct pw_context *context,
|
int pw_context_find_format(struct pw_context *context,
|
||||||
struct pw_impl_port *output,
|
struct pw_impl_port *output,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue