diff --git a/pinos/client/connection.c b/pinos/client/connection.c index d246d3e3f..aa9faa150 100644 --- a/pinos/client/connection.c +++ b/pinos/client/connection.c @@ -1021,7 +1021,7 @@ pinos_connection_flush (PinosConnection *conn) } while (true) { - len = sendmsg (conn->fd, &msg, 0); + len = sendmsg (conn->fd, &msg, MSG_NOSIGNAL); if (len < 0) { if (errno == EINTR) continue; diff --git a/pinos/gst/gstpinossrc.c b/pinos/gst/gstpinossrc.c index f0f2e2cae..0c0154122 100644 --- a/pinos/gst/gstpinossrc.c +++ b/pinos/gst/gstpinossrc.c @@ -180,6 +180,12 @@ gst_pinos_src_finalize (GObject * object) g_queue_foreach (&pinossrc->queue, (GFunc) gst_mini_object_unref, NULL); g_queue_clear (&pinossrc->queue); + + pinos_thread_main_loop_destroy (pinossrc->main_loop); + pinossrc->main_loop = NULL; + pinos_loop_destroy (pinossrc->loop); + pinossrc->loop = NULL; + if (pinossrc->properties) gst_structure_free (pinossrc->properties); g_object_unref (pinossrc->fd_allocator); @@ -275,6 +281,10 @@ gst_pinos_src_init (GstPinosSrc * src) src->fd_allocator = gst_fd_allocator_new (); src->client_name = pinos_client_name (); src->buf_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) gst_buffer_unref); + + src->loop = pinos_loop_new (); + src->main_loop = pinos_thread_main_loop_new (src->loop, "pinos-main-loop"); + GST_DEBUG ("loop %p, mainloop %p", src->loop, src->main_loop); } static GstCaps * @@ -989,10 +999,6 @@ gst_pinos_src_open (GstPinosSrc * pinossrc) { PinosProperties *props; - pinossrc->loop = pinos_loop_new (); - GST_DEBUG ("loop %p", pinossrc->loop); - - pinossrc->main_loop = pinos_thread_main_loop_new (pinossrc->loop, "pinos-main-loop"); if (pinos_thread_main_loop_start (pinossrc->main_loop) != SPA_RESULT_OK) goto mainloop_failed; @@ -1052,24 +1058,19 @@ connect_error: static void gst_pinos_src_close (GstPinosSrc * pinossrc) { + clear_queue (pinossrc); + pinos_thread_main_loop_stop (pinossrc->main_loop); - pinos_thread_main_loop_destroy (pinossrc->main_loop); - pinossrc->main_loop = NULL; + + pinos_stream_destroy (pinossrc->stream); + pinossrc->stream = NULL; pinos_context_destroy (pinossrc->ctx); pinossrc->ctx = NULL; - pinos_loop_destroy (pinossrc->loop); - pinossrc->loop = NULL; - GST_OBJECT_LOCK (pinossrc); g_clear_object (&pinossrc->clock); - g_clear_object (&pinossrc->stream); GST_OBJECT_UNLOCK (pinossrc); - clear_queue (pinossrc); - if (pinossrc->clock) - gst_object_unref (pinossrc->clock); - pinossrc->clock = NULL; } static GstStateChangeReturn diff --git a/pinos/modules/module-protocol-native.c b/pinos/modules/module-protocol-native.c index df4cc8fdc..9f85dddee 100644 --- a/pinos/modules/module-protocol-native.c +++ b/pinos/modules/module-protocol-native.c @@ -124,15 +124,30 @@ object_new (size_t size, } static void -object_destroy (PinosProtocolNativeObject *this) +sync_destroy (void *object, + void *data, + SpaResult res, + uint32_t id) { - spa_list_remove (&this->link); + PinosProtocolNativeObject *this = object; if (this->destroy) this->destroy (this); free (this); } +static void +object_destroy (PinosProtocolNativeObject *this) +{ + spa_list_remove (&this->link); + + pinos_main_loop_defer (this->impl->core->main_loop, + this, + SPA_RESULT_WAIT_SYNC, + sync_destroy, + this); +} + static PinosProtocolNativeObject * find_object (PinosProtocolNative *impl, void *object) @@ -149,8 +164,9 @@ static void client_destroy (PinosProtocolNativeClient *this) { spa_list_remove (&this->link); - pinos_loop_destroy_source (this->parent.impl->core->main_loop->loop, - this->source); + if (this->source) + pinos_loop_destroy_source (this->parent.impl->core->main_loop->loop, + this->source); pinos_connection_destroy (this->connection); close (this->fd); } @@ -276,6 +292,10 @@ connection_data (SpaSource *source, size_t size; if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { + pinos_log_debug ("protocol-native %p: got connection error", client->parent.impl); + pinos_loop_destroy_source (client->parent.impl->core->main_loop->loop, + client->source); + client->source = NULL; pinos_client_destroy (client->parent.global->object); return; } diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index 2886ba931..83352a218 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -1274,14 +1274,15 @@ pinos_client_node_new (PinosClient *client, } static void -on_node_remove (PinosNode *node, +on_node_remove (void *object, void *data, - SpaResult res) + SpaResult res, + uint32_t id) { - PinosClientNode *this = data; + PinosClientNode *this = object; PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); - pinos_log_debug ("client-node %p: finalize", node); + pinos_log_debug ("client-node %p: finalize", this); proxy_clear (&impl->proxy); if (impl->data_fd != -1) @@ -1290,24 +1291,21 @@ on_node_remove (PinosNode *node, } -SpaResult +void pinos_client_node_destroy (PinosClientNode * this) { PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); - SpaResult res; pinos_log_debug ("client-node %p: destroy", impl); pinos_signal_emit (&this->destroy_signal, this); - res = pinos_node_destroy (this->node); + pinos_node_destroy (this->node); pinos_main_loop_defer (this->node->core->main_loop, - this->node, - res, + this, + SPA_RESULT_WAIT_SYNC, (PinosDeferFunc) on_node_remove, this); - - return res; } /** diff --git a/pinos/server/client-node.h b/pinos/server/client-node.h index afec213bd..4798188fb 100644 --- a/pinos/server/client-node.h +++ b/pinos/server/client-node.h @@ -50,7 +50,7 @@ PinosClientNode * pinos_client_node_new (PinosClient *client, uint32_t id, const char *name, PinosProperties *properties); -SpaResult pinos_client_node_destroy (PinosClientNode *node); +void pinos_client_node_destroy (PinosClientNode *node); SpaResult pinos_client_node_get_data_socket (PinosClientNode *node, int *fd); diff --git a/pinos/server/client.c b/pinos/server/client.c index f4f594737..8f6eaf536 100644 --- a/pinos/server/client.c +++ b/pinos/server/client.c @@ -63,32 +63,46 @@ pinos_client_new (PinosCore *core, return this; } +static void +sync_destroy (void *object, + void *data, + SpaResult res, + uint32_t id) +{ + PinosClientImpl *impl = SPA_CONTAINER_OF (object, PinosClientImpl, this); + PinosClient *client = &impl->this; + + pinos_log_debug ("client %p: sync destroy", impl); + + if (client->properties) + pinos_properties_free (client->properties); + + free (impl); +} + /** * pinos_client_destroy: * @client: a #PinosClient * * Trigger removal of @client */ -SpaResult +void pinos_client_destroy (PinosClient * client) { - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this); PinosResource *resource, *tmp; pinos_log_debug ("client %p: destroy", client); pinos_signal_emit (&client->destroy_signal, client); - pinos_global_destroy (client->global); - spa_list_for_each_safe (resource, tmp, &client->resource_list, link) pinos_resource_destroy (resource); + pinos_global_destroy (client->global); spa_list_remove (&client->link); - if (client->properties) - pinos_properties_free (client->properties); - - free (impl); - - return SPA_RESULT_OK; + pinos_main_loop_defer (client->core->main_loop, + client, + SPA_RESULT_WAIT_SYNC, + sync_destroy, + client); } diff --git a/pinos/server/client.h b/pinos/server/client.h index 2dfe9f4dd..a1ac4d0f4 100644 --- a/pinos/server/client.h +++ b/pinos/server/client.h @@ -55,7 +55,7 @@ struct _PinosClient { PinosClient * pinos_client_new (PinosCore *core, PinosProperties *properties); -SpaResult pinos_client_destroy (PinosClient *client); +void pinos_client_destroy (PinosClient *client); #ifdef __cplusplus } diff --git a/pinos/server/core.c b/pinos/server/core.c index 9fa54fc69..1665d902b 100644 --- a/pinos/server/core.c +++ b/pinos/server/core.c @@ -114,11 +114,24 @@ pinos_core_add_global (PinosCore *core, return global; } -SpaResult +static void +sync_destroy (void *object, + void *data, + SpaResult res, + uint32_t id) +{ + PinosGlobal *global = object; + + pinos_log_debug ("global %p: sync destroy", global); + free (global); +} + +void pinos_global_destroy (PinosGlobal *global) { PinosCore *core = global->core; + pinos_log_debug ("global %p: destroy", global); pinos_signal_emit (&global->destroy_signal, global); pinos_map_remove (&core->objects, global->id); @@ -126,9 +139,11 @@ pinos_global_destroy (PinosGlobal *global) spa_list_remove (&global->link); pinos_signal_emit (&core->global_removed, core, global); - free (global); - - return SPA_RESULT_OK; + pinos_main_loop_defer (core->main_loop, + global, + SPA_RESULT_WAIT_SYNC, + sync_destroy, + global); } PinosPort * diff --git a/pinos/server/core.h b/pinos/server/core.h index 7f2a7aadc..d68c1dd38 100644 --- a/pinos/server/core.h +++ b/pinos/server/core.h @@ -115,7 +115,7 @@ void pinos_core_destroy (PinosCore *core); PinosGlobal * pinos_core_add_global (PinosCore *core, uint32_t type, void *object); -SpaResult pinos_global_destroy (PinosGlobal *global); +void pinos_global_destroy (PinosGlobal *global); PinosPort * pinos_core_find_port (PinosCore *core, diff --git a/pinos/server/link.c b/pinos/server/link.c index 29450fc0e..f1d66b12f 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -154,6 +154,7 @@ again: asprintf (&error, "error set output format: %d", res); goto error; } + pinos_main_loop_defer (this->core->main_loop, this->output->node, res, NULL, NULL); } else if (in_state == SPA_NODE_STATE_CONFIGURE) { pinos_log_debug ("link %p: doing set format on input", this); if ((res = spa_node_port_set_format (this->input->node->node, @@ -164,6 +165,7 @@ again: asprintf (&error, "error set input format: %d", res); goto error; } + pinos_main_loop_defer (this->core->main_loop, this->input->node, res, NULL, NULL); } return res; @@ -419,6 +421,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) asprintf (&error, "error alloc output buffers: %d", res); goto error; } + pinos_main_loop_defer (this->core->main_loop, this->output->node, res, NULL, NULL); this->output->buffers = impl->buffers; this->output->n_buffers = impl->n_buffers; this->output->allocated = TRUE; @@ -434,6 +437,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) asprintf (&error, "error alloc input buffers: %d", res); goto error; } + pinos_main_loop_defer (this->core->main_loop, this->input->node, res, NULL, NULL); this->input->buffers = impl->buffers; this->input->n_buffers = impl->n_buffers; this->input->allocated = TRUE; @@ -453,6 +457,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) asprintf (&error, "error use input buffers: %d", res); goto error; } + pinos_main_loop_defer (this->core->main_loop, this->input->node, res, NULL, NULL); this->input->buffers = impl->buffers; this->input->n_buffers = impl->n_buffers; this->input->allocated = FALSE; @@ -467,6 +472,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) asprintf (&error, "error use output buffers: %d", res); goto error; } + pinos_main_loop_defer (this->core->main_loop, this->output->node, res, NULL, NULL); this->output->buffers = impl->buffers; this->output->n_buffers = impl->n_buffers; this->output->allocated = FALSE; @@ -519,11 +525,6 @@ check_states (PinosLink *this, { SpaNodeState in_state, out_state; - if (res != SPA_RESULT_OK) { - pinos_log_warn ("link %p: error: %d", this, res); - return res; - } - again: if (this->input == NULL || this->output == NULL) return SPA_RESULT_OK; @@ -550,7 +551,11 @@ again: return SPA_RESULT_OK; exit: - pinos_main_loop_defer (this->core->main_loop, this, res, (PinosDeferFunc) check_states, this); + pinos_main_loop_defer (this->core->main_loop, + this, + SPA_RESULT_WAIT_SYNC, + (PinosDeferFunc) check_states, + this); return res; } @@ -740,7 +745,6 @@ do_link_remove_done (SpaLoop *loop, void *user_data) { PinosLink *this = user_data; - PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this); if (this->input) { spa_list_remove (&this->input_link); @@ -765,12 +769,10 @@ do_link_remove_done (SpaLoop *loop, this->output = NULL; } - pinos_main_loop_defer_cancel (this->core->main_loop, this, 0); - - if (impl->allocated) - pinos_memblock_free (&impl->buffer_mem); - - free (impl); + pinos_main_loop_defer_complete (this->core->main_loop, + this, + seq, + SPA_RESULT_OK); return SPA_RESULT_OK; } @@ -804,13 +806,29 @@ do_link_remove (SpaLoop *loop, return res; } +static void +sync_destroy (void *object, + void *data, + SpaResult res, + uint32_t id) +{ + PinosLinkImpl *impl = SPA_CONTAINER_OF (object, PinosLinkImpl, this); + + pinos_log_debug ("link %p: sync destroy", impl); + + if (impl->allocated) + pinos_memblock_free (&impl->buffer_mem); + + free (impl); +} + /** * pinos_link_destroy: * @link: a #PinosLink * * Trigger removal of @link */ -SpaResult +void pinos_link_destroy (PinosLink * this) { SpaResult res = SPA_RESULT_OK; @@ -832,6 +850,8 @@ pinos_link_destroy (PinosLink * this) 0, NULL, this); + + pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL); } if (this->output) { pinos_signal_remove (&impl->output_port_destroy); @@ -843,6 +863,12 @@ pinos_link_destroy (PinosLink * this) 0, NULL, this); + pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL); } - return res; + + pinos_main_loop_defer (this->core->main_loop, + this, + SPA_RESULT_WAIT_SYNC, + sync_destroy, + this); } diff --git a/pinos/server/link.h b/pinos/server/link.h index 2b2c39eaa..8a482dd34 100644 --- a/pinos/server/link.h +++ b/pinos/server/link.h @@ -79,7 +79,7 @@ PinosLink * pinos_link_new (PinosCore *core, PinosPort *input, SpaFormat **format_filter, PinosProperties *properties); -SpaResult pinos_link_destroy (PinosLink *link); +void pinos_link_destroy (PinosLink *link); bool pinos_link_activate (PinosLink *link); bool pinos_link_deactivate (PinosLink *link); diff --git a/pinos/server/main-loop.c b/pinos/server/main-loop.c index 16c97a620..f98b7f94c 100644 --- a/pinos/server/main-loop.c +++ b/pinos/server/main-loop.c @@ -64,8 +64,15 @@ process_work_queue (SpaSource *source, WorkItem *item, *tmp; spa_list_for_each_safe (item, tmp, &impl->work_list, link) { - if (item->seq != SPA_ID_INVALID) + if (item->seq != SPA_ID_INVALID) { + pinos_log_debug ("main-loop %p: waiting for item %p %d", this, item->obj, item->seq); continue; + } + + if (item->res == SPA_RESULT_WAIT_SYNC && item != spa_list_first (&impl->work_list, WorkItem, link)) { + pinos_log_debug ("main-loop %p: sync item %p not head", this, item->obj); + continue; + } spa_list_remove (&item->link); @@ -78,11 +85,11 @@ process_work_queue (SpaSource *source, } static uint32_t -do_add_work (PinosMainLoop *loop, - void *obj, - SpaResult res, - PinosDeferFunc func, - void *data) +main_loop_defer (PinosMainLoop *loop, + void *obj, + SpaResult res, + PinosDeferFunc func, + void *data) { PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); WorkItem *item; @@ -103,6 +110,11 @@ do_add_work (PinosMainLoop *loop, item->seq = SPA_RESULT_ASYNC_SEQ (res); item->res = res; pinos_log_debug ("main-loop %p: defer async %d for object %p", loop, item->seq, obj); + } else if (res == SPA_RESULT_WAIT_SYNC) { + pinos_log_debug ("main-loop %p: wait sync object %p", loop, obj); + item->seq = SPA_ID_INVALID; + item->res = res; + have_work = TRUE; } else { item->seq = SPA_ID_INVALID; item->res = res; @@ -117,16 +129,6 @@ do_add_work (PinosMainLoop *loop, return item->id; } -static uint32_t -main_loop_defer (PinosMainLoop *loop, - void *obj, - SpaResult res, - PinosDeferFunc func, - void *data) -{ - return do_add_work (loop, obj, res, func, data); -} - static void main_loop_defer_cancel (PinosMainLoop *loop, void *obj, @@ -175,28 +177,6 @@ main_loop_defer_complete (PinosMainLoop *loop, return have_work; } -static void -main_loop_quit (PinosMainLoop *loop) -{ - PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); - pinos_log_debug ("main-loop %p: quit", impl); - impl->running = false; -} - -static void -main_loop_run (PinosMainLoop *loop) -{ - PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); - - pinos_log_debug ("main-loop %p: run", impl); - - impl->running = true; - pinos_loop_enter (loop->loop); - while (impl->running) { - pinos_loop_iterate (loop->loop, -1); - } - pinos_loop_leave (loop->loop); -} /** * pinos_main_loop_new: @@ -223,8 +203,6 @@ pinos_main_loop_new (void) process_work_queue, impl); - this->run = main_loop_run; - this->quit = main_loop_quit; this->defer = main_loop_defer; this->defer_cancel = main_loop_defer_cancel; this->defer_complete = main_loop_defer_complete; @@ -251,3 +229,26 @@ pinos_main_loop_destroy (PinosMainLoop *loop) free (item); free (impl); } + +void +pinos_main_loop_quit (PinosMainLoop *loop) +{ + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + pinos_log_debug ("main-loop %p: quit", impl); + impl->running = false; +} + +void +pinos_main_loop_run (PinosMainLoop *loop) +{ + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + + pinos_log_debug ("main-loop %p: run", impl); + + impl->running = true; + pinos_loop_enter (loop->loop); + while (impl->running) { + pinos_loop_iterate (loop->loop, -1); + } + pinos_loop_leave (loop->loop); +} diff --git a/pinos/server/main-loop.h b/pinos/server/main-loop.h index fe14e372c..60cf26049 100644 --- a/pinos/server/main-loop.h +++ b/pinos/server/main-loop.h @@ -45,9 +45,6 @@ struct _PinosMainLoop { PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosMainLoop *loop)); - void (*run) (PinosMainLoop *loop); - void (*quit) (PinosMainLoop *loop); - uint32_t (*defer) (PinosMainLoop *loop, void *obj, SpaResult res, @@ -65,13 +62,12 @@ struct _PinosMainLoop { PinosMainLoop * pinos_main_loop_new (void); void pinos_main_loop_destroy (PinosMainLoop *loop); -#define pinos_main_loop_run(m) (m)->run(m) -#define pinos_main_loop_quit(m) (m)->quit(m) +void pinos_main_loop_run (PinosMainLoop *loop); +void pinos_main_loop_quit (PinosMainLoop *loop); #define pinos_main_loop_defer(m,...) (m)->defer(m,__VA_ARGS__) #define pinos_main_loop_defer_cancel(m,...) (m)->defer_cancel(m,__VA_ARGS__) #define pinos_main_loop_defer_complete(m,...) (m)->defer_complete(m,__VA_ARGS__) -#define pinos_main_loop_sync(m,...) (m)->sync(m,__VA_ARGS__) #ifdef __cplusplus } diff --git a/pinos/server/node.c b/pinos/server/node.c index d6d2c29f7..965398304 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -477,22 +477,19 @@ do_node_remove_done (SpaLoop *loop, void *user_data) { PinosNode *this = user_data; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); PinosPort *port, *tmp; - pinos_main_loop_defer_cancel (this->core->main_loop, this, 0); - + pinos_log_debug ("node %p: remove done, destroy ports", this); spa_list_for_each_safe (port, tmp, &this->input_ports, link) pinos_port_destroy (port); spa_list_for_each_safe (port, tmp, &this->output_ports, link) pinos_port_destroy (port); - free (this->name); - free (this->error); - if (this->properties) - pinos_properties_free (this->properties); - free (impl); + pinos_main_loop_defer_complete (this->core->main_loop, + this, + seq, + SPA_RESULT_OK); return SPA_RESULT_OK; } @@ -536,6 +533,24 @@ do_node_remove (SpaLoop *loop, return res; } +static void +sync_destroy (void *object, + void *data, + SpaResult res, + uint32_t id) +{ + PinosNode *this = object; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); + + pinos_log_debug ("node %p: sync destroy", this); + + free (this->name); + free (this->error); + if (this->properties) + pinos_properties_free (this->properties); + free (impl); +} + /** * pinos_node_destroy: * @node: a #PinosNode @@ -543,7 +558,7 @@ do_node_remove (SpaLoop *loop, * Remove @node. This will stop the transfer on the node and * free the resources allocated by @node. */ -SpaResult +void pinos_node_destroy (PinosNode * this) { SpaResult res; @@ -561,7 +576,18 @@ pinos_node_destroy (PinosNode * this) 0, NULL, this); - return res; + + pinos_main_loop_defer (this->core->main_loop, + this, + res, + NULL, + NULL); + + pinos_main_loop_defer (this->core->main_loop, + this, + SPA_RESULT_WAIT_SYNC, + sync_destroy, + this); } /** diff --git a/pinos/server/node.h b/pinos/server/node.h index 4947f0658..03c42fad7 100644 --- a/pinos/server/node.h +++ b/pinos/server/node.h @@ -94,7 +94,7 @@ PinosNode * pinos_node_new (PinosCore *core, SpaNode *node, SpaClock *clock, PinosProperties *properties); -SpaResult pinos_node_destroy (PinosNode *node); +void pinos_node_destroy (PinosNode *node); void pinos_node_set_data_loop (PinosNode *node, diff --git a/pinos/server/port.c b/pinos/server/port.c index 1b20bde36..6a25e0d07 100644 --- a/pinos/server/port.c +++ b/pinos/server/port.c @@ -54,6 +54,17 @@ pinos_port_new (PinosNode *node, return this; } +static void +sync_destroy (void *object, + void *data, + SpaResult res, + uint32_t id) +{ + PinosPort *port = object; + + free (port); +} + void pinos_port_destroy (PinosPort *port) { @@ -61,6 +72,8 @@ pinos_port_destroy (PinosPort *port) pinos_signal_emit (&port->destroy_signal, port); + spa_list_remove (&port->link); + spa_node_port_use_buffers (port->node->node, port->direction, port->port_id, @@ -68,8 +81,11 @@ pinos_port_destroy (PinosPort *port) port->buffers = NULL; port->n_buffers = 0; - spa_list_remove (&port->link); - free (port); + pinos_main_loop_defer (port->node->core->main_loop, + port, + SPA_RESULT_WAIT_SYNC, + sync_destroy, + port); } static SpaResult diff --git a/pinos/server/resource.c b/pinos/server/resource.c index 9b43c0b97..6ee693af6 100644 --- a/pinos/server/resource.c +++ b/pinos/server/resource.c @@ -50,6 +50,17 @@ pinos_resource_new (PinosClient *client, return resource; } +static void +sync_destroy (void *object, + void *data, + SpaResult res, + uint32_t id) +{ + PinosResource *resource = object; + pinos_log_debug ("resource %p: sync destroy", resource); + free (resource); +} + SpaResult pinos_resource_destroy (PinosResource *resource) { @@ -61,7 +72,11 @@ pinos_resource_destroy (PinosResource *resource) if (resource->destroy) resource->destroy (resource->object); - free (resource); + pinos_main_loop_defer (resource->core->main_loop, + resource, + SPA_RESULT_WAIT_SYNC, + sync_destroy, + resource); return SPA_RESULT_OK; } diff --git a/spa/include/spa/defs.h b/spa/include/spa/defs.h index a5cf6edf7..b0502c2b3 100644 --- a/spa/include/spa/defs.h +++ b/spa/include/spa/defs.h @@ -32,6 +32,7 @@ extern "C" { typedef enum { SPA_RESULT_ASYNC = (1 << 30), + SPA_RESULT_WAIT_SYNC = 2, SPA_RESULT_MODIFIED = 1, SPA_RESULT_OK = 0, SPA_RESULT_ERROR = -1, diff --git a/spa/include/spa/dict.h b/spa/include/spa/dict.h index 1ad9d5526..18c221208 100644 --- a/spa/include/spa/dict.h +++ b/spa/include/spa/dict.h @@ -40,16 +40,27 @@ struct _SpaDict { SpaDictItem *items; }; +#define spa_dict_for_each(item, dict) \ + for ((item) = (dict)->items; \ + (item) < &(dict)->items[(dict)->n_items]; \ + (item)++) + +static inline SpaDictItem * +spa_dict_lookup_item (const SpaDict *dict, const char *key) +{ + SpaDictItem *item; + spa_dict_for_each (item, dict) { + if (!strcmp (item->key, key)) + return item; + } + return NULL; +} + static inline const char * spa_dict_lookup (const SpaDict *dict, const char *key) { - unsigned int i; - - for (i = 0; i < dict->n_items; i++) { - if (!strcmp (dict->items[i].key, key)) - return dict->items[i].value; - } - return NULL; + SpaDictItem *item = spa_dict_lookup_item (dict, key); + return item ? item->value : NULL; } #ifdef __cplusplus