list: add _consume method

Add safer way to destroy a list of objects.
This commit is contained in:
Wim Taymans 2019-05-06 17:04:16 +02:00
parent fa0b4f9321
commit 2b5c6fd676
11 changed files with 43 additions and 38 deletions

View file

@ -78,6 +78,11 @@ static inline void spa_list_remove(struct spa_list *elem)
#define spa_list_next(pos, member) \ #define spa_list_next(pos, member) \
SPA_CONTAINER_OF((pos)->member.next, __typeof__(*pos), member) SPA_CONTAINER_OF((pos)->member.next, __typeof__(*pos), member)
#define spa_list_consume(pos, head, member) \
for (pos = spa_list_first(head, __typeof__(*pos), member); \
!spa_list_is_empty(head); \
pos = spa_list_first(head, __typeof__(*pos), member))
#define spa_list_for_each_next(pos, head, curr, member) \ #define spa_list_for_each_next(pos, head, curr, member) \
for (pos = spa_list_first(curr, __typeof__(*pos), member); \ for (pos = spa_list_first(curr, __typeof__(*pos), member); \
!spa_list_is_end(pos, head, member); \ !spa_list_is_end(pos, head, member); \

View file

@ -686,13 +686,13 @@ static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id,
static int impl_clear(struct spa_handle *handle) static int impl_clear(struct spa_handle *handle)
{ {
struct impl *impl; struct impl *impl;
struct source_impl *source, *tmp; struct source_impl *source;
spa_return_val_if_fail(handle != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL);
impl = (struct impl *) handle; impl = (struct impl *) handle;
spa_list_for_each_safe(source, tmp, &impl->source_list, link) spa_list_consume(source, &impl->source_list, link)
loop_destroy_source(&source->source); loop_destroy_source(&source->source);
process_destroy(impl); process_destroy(impl);

View file

@ -716,11 +716,11 @@ impl_new_client(struct pw_protocol *protocol,
static void destroy_server(struct pw_protocol_server *server) static void destroy_server(struct pw_protocol_server *server)
{ {
struct server *s = SPA_CONTAINER_OF(server, struct server, this); struct server *s = SPA_CONTAINER_OF(server, struct server, this);
struct pw_client *client, *tmp; struct pw_client *client;
spa_list_remove(&server->link); spa_list_remove(&server->link);
spa_list_for_each_safe(client, tmp, &server->client_list, protocol_link) spa_list_consume(client, &server->client_list, protocol_link)
pw_client_destroy(client); pw_client_destroy(client);
if (s->source) if (s->source)

View file

@ -105,7 +105,7 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions,
data = pw_resource_get_user_data(resource); data = pw_resource_get_user_data(resource);
pw_resource_add_listener(resource, &data->resource_listener, &resource_events, resource); pw_resource_add_listener(resource, &data->resource_listener, &resource_events, resource);
pw_log_debug("client %p: bound to %d", this, resource->id); pw_log_debug("client %p: bound to %p %d", this, resource, resource->id);
spa_list_append(&this->resource_list, &resource->link); spa_list_append(&this->resource_list, &resource->link);
@ -305,7 +305,7 @@ static int destroy_resource(void *object, void *data)
SPA_EXPORT SPA_EXPORT
void pw_client_destroy(struct pw_client *client) void pw_client_destroy(struct pw_client *client)
{ {
struct pw_resource *resource, *tmp; struct pw_resource *resource;
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
pw_log_debug("client %p: destroy", client); pw_log_debug("client %p: destroy", client);
@ -321,7 +321,7 @@ void pw_client_destroy(struct pw_client *client)
pw_global_destroy(client->global); pw_global_destroy(client->global);
} }
spa_list_for_each_safe(resource, tmp, &client->resource_list, link) spa_list_consume(resource, &client->resource_list, link)
pw_resource_destroy(resource); pw_resource_destroy(resource);
pw_map_for_each(&client->objects, destroy_resource, client); pw_map_for_each(&client->objects, destroy_resource, client);

View file

@ -473,26 +473,26 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, struct pw_properties *pro
SPA_EXPORT SPA_EXPORT
void pw_core_destroy(struct pw_core *core) void pw_core_destroy(struct pw_core *core)
{ {
struct pw_global *global, *t; struct pw_global *global;
struct pw_module *module, *tm; struct pw_module *module;
struct pw_remote *remote, *tr; struct pw_remote *remote;
struct pw_node *node, *tn; struct pw_node *node;
pw_log_debug("core %p: destroy", core); pw_log_debug("core %p: destroy", core);
pw_core_events_destroy(core); pw_core_events_destroy(core);
spa_hook_remove(&core->global_listener); spa_hook_remove(&core->global_listener);
spa_list_for_each_safe(remote, tr, &core->remote_list, link) spa_list_consume(remote, &core->remote_list, link)
pw_remote_destroy(remote); pw_remote_destroy(remote);
spa_list_for_each_safe(module, tm, &core->module_list, link) spa_list_consume(module, &core->module_list, link)
pw_module_destroy(module); pw_module_destroy(module);
spa_list_for_each_safe(node, tn, &core->node_list, link) spa_list_consume(node, &core->node_list, link)
pw_node_destroy(node); pw_node_destroy(node);
spa_list_for_each_safe(global, t, &core->global_list, link) spa_list_consume(global, &core->global_list, link)
pw_global_destroy(global); pw_global_destroy(global);
pw_core_events_free(core); pw_core_events_free(core);

View file

@ -1278,7 +1278,7 @@ SPA_EXPORT
void pw_link_destroy(struct pw_link *link) void pw_link_destroy(struct pw_link *link)
{ {
struct impl *impl = SPA_CONTAINER_OF(link, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(link, struct impl, this);
struct pw_resource *resource, *tmp; struct pw_resource *resource;
pw_log_debug("link %p: destroy", impl); pw_log_debug("link %p: destroy", impl);
pw_link_events_destroy(link); pw_link_events_destroy(link);
@ -1300,7 +1300,7 @@ void pw_link_destroy(struct pw_link *link)
pw_global_destroy(link->global); pw_global_destroy(link->global);
} }
spa_list_for_each_safe(resource, tmp, &link->resource_list, link) spa_list_consume(resource, &link->resource_list, link)
pw_resource_destroy(resource); pw_resource_destroy(resource);
pw_log_debug("link %p: free", impl); pw_log_debug("link %p: free", impl);

View file

@ -287,7 +287,7 @@ SPA_EXPORT
void pw_module_destroy(struct pw_module *module) void pw_module_destroy(struct pw_module *module)
{ {
struct impl *impl = SPA_CONTAINER_OF(module, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(module, struct impl, this);
struct pw_resource *resource, *tmp; struct pw_resource *resource;
pw_log_debug("module %p: destroy", module); pw_log_debug("module %p: destroy", module);
pw_module_events_destroy(module); pw_module_events_destroy(module);
@ -298,7 +298,7 @@ void pw_module_destroy(struct pw_module *module)
spa_hook_remove(&module->global_listener); spa_hook_remove(&module->global_listener);
pw_global_destroy(module->global); pw_global_destroy(module->global);
} }
spa_list_for_each_safe(resource, tmp, &module->resource_list, link) spa_list_consume(resource, &module->resource_list, link)
pw_resource_destroy(resource); pw_resource_destroy(resource);
free((char *) module->info.name); free((char *) module->info.name);

View file

@ -624,8 +624,8 @@ SPA_EXPORT
void pw_node_destroy(struct pw_node *node) void pw_node_destroy(struct pw_node *node)
{ {
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
struct pw_resource *resource, *tmp; struct pw_resource *resource;
struct pw_port *port, *tmpp; struct pw_port *port;
pw_log_debug("node %p: destroy", impl); pw_log_debug("node %p: destroy", impl);
pw_node_events_destroy(node); pw_node_events_destroy(node);
@ -642,11 +642,11 @@ void pw_node_destroy(struct pw_node *node)
pw_port_unlink(port); pw_port_unlink(port);
pw_log_debug("node %p: destroy ports", node); pw_log_debug("node %p: destroy ports", node);
spa_list_for_each_safe(port, tmpp, &node->input_ports, link) { spa_list_consume(port, &node->input_ports, link) {
pw_node_events_port_removed(node, port); pw_node_events_port_removed(node, port);
pw_port_destroy(port); pw_port_destroy(port);
} }
spa_list_for_each_safe(port, tmpp, &node->output_ports, link) { spa_list_consume(port, &node->output_ports, link) {
pw_node_events_port_removed(node, port); pw_node_events_port_removed(node, port);
pw_port_destroy(port); pw_port_destroy(port);
} }
@ -655,7 +655,7 @@ void pw_node_destroy(struct pw_node *node)
spa_hook_remove(&node->global_listener); spa_hook_remove(&node->global_listener);
pw_global_destroy(node->global); pw_global_destroy(node->global);
} }
spa_list_for_each_safe(resource, tmp, &node->resource_list, link) spa_list_consume(resource, &node->resource_list, link)
pw_resource_destroy(resource); pw_resource_destroy(resource);
pw_log_debug("node %p: free", node); pw_log_debug("node %p: free", node);

View file

@ -542,8 +542,8 @@ static void pw_port_remove(struct pw_port *port)
void pw_port_destroy(struct pw_port *port) void pw_port_destroy(struct pw_port *port)
{ {
struct pw_node *node = port->node; struct pw_node *node = port->node;
struct pw_control *control, *ctemp; struct pw_control *control;
struct pw_resource *resource, *tmp; struct pw_resource *resource;
pw_log_debug("port %p: destroy", port); pw_log_debug("port %p: destroy", port);
@ -552,16 +552,16 @@ void pw_port_destroy(struct pw_port *port)
if (node) if (node)
pw_port_remove(port); pw_port_remove(port);
spa_list_for_each_safe(control, ctemp, &port->control_list[0], port_link) spa_list_consume(control, &port->control_list[0], port_link)
pw_control_destroy(control); pw_control_destroy(control);
spa_list_for_each_safe(control, ctemp, &port->control_list[1], port_link) spa_list_consume(control, &port->control_list[1], port_link)
pw_control_destroy(control); pw_control_destroy(control);
if (port->global) { if (port->global) {
spa_hook_remove(&port->global_listener); spa_hook_remove(&port->global_listener);
pw_global_destroy(port->global); pw_global_destroy(port->global);
} }
spa_list_for_each_safe(resource, tmp, &port->resource_list, link) spa_list_consume(resource, &port->resource_list, link)
pw_resource_destroy(resource); pw_resource_destroy(resource);
pw_log_debug("port %p: free", port); pw_log_debug("port %p: free", port);

View file

@ -88,18 +88,18 @@ void pw_protocol_destroy(struct pw_protocol *protocol)
{ {
struct impl *impl = SPA_CONTAINER_OF(protocol, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(protocol, struct impl, this);
struct marshal *marshal, *t1; struct marshal *marshal, *t1;
struct pw_protocol_server *server, *t2; struct pw_protocol_server *server;
struct pw_protocol_client *client, *t3; struct pw_protocol_client *client;
pw_log_debug("protocol %p: destroy", protocol); pw_log_debug("protocol %p: destroy", protocol);
pw_protocol_events_destroy(protocol); pw_protocol_events_destroy(protocol);
spa_list_remove(&protocol->link); spa_list_remove(&protocol->link);
spa_list_for_each_safe(server, t2, &protocol->server_list, link) spa_list_consume(server, &protocol->server_list, link)
pw_protocol_server_destroy(server); pw_protocol_server_destroy(server);
spa_list_for_each_safe(client, t3, &protocol->client_list, link) spa_list_consume(client, &protocol->client_list, link)
pw_protocol_client_destroy(client); pw_protocol_client_destroy(client);
spa_list_for_each_safe(marshal, t1, &protocol->marshal_list, link) spa_list_for_each_safe(marshal, t1, &protocol->marshal_list, link)

View file

@ -292,7 +292,7 @@ SPA_EXPORT
void pw_remote_destroy(struct pw_remote *remote) void pw_remote_destroy(struct pw_remote *remote)
{ {
struct remote *impl = SPA_CONTAINER_OF(remote, struct remote, this); struct remote *impl = SPA_CONTAINER_OF(remote, struct remote, this);
struct pw_stream *stream, *s2; struct pw_stream *stream;
pw_log_debug("remote %p: destroy", remote); pw_log_debug("remote %p: destroy", remote);
pw_remote_events_destroy(remote); pw_remote_events_destroy(remote);
@ -300,7 +300,7 @@ void pw_remote_destroy(struct pw_remote *remote)
if (remote->state != PW_REMOTE_STATE_UNCONNECTED) if (remote->state != PW_REMOTE_STATE_UNCONNECTED)
pw_remote_disconnect(remote); pw_remote_disconnect(remote);
spa_list_for_each_safe(stream, s2, &remote->stream_list, link) spa_list_consume(stream, &remote->stream_list, link)
pw_stream_destroy(stream); pw_stream_destroy(stream);
pw_protocol_client_destroy (remote->conn); pw_protocol_client_destroy (remote->conn);
@ -449,14 +449,14 @@ int pw_remote_steal_fd(struct pw_remote *remote)
SPA_EXPORT SPA_EXPORT
int pw_remote_disconnect(struct pw_remote *remote) int pw_remote_disconnect(struct pw_remote *remote)
{ {
struct pw_proxy *proxy, *t2; struct pw_proxy *proxy;
struct pw_stream *stream, *s2; struct pw_stream *stream, *s2;
pw_log_debug("remote %p: disconnect", remote); pw_log_debug("remote %p: disconnect", remote);
spa_list_for_each_safe(stream, s2, &remote->stream_list, link) spa_list_for_each_safe(stream, s2, &remote->stream_list, link)
pw_stream_disconnect(stream); pw_stream_disconnect(stream);
spa_list_for_each_safe(proxy, t2, &remote->proxy_list, link) spa_list_consume(proxy, &remote->proxy_list, link)
pw_proxy_destroy(proxy); pw_proxy_destroy(proxy);
remote->core_proxy = NULL; remote->core_proxy = NULL;