Work on async cleanup

Track all async changes and only perform free of resources when all
previous async operations completed.
This commit is contained in:
Wim Taymans 2016-11-25 13:06:23 +01:00
parent 7ecfc28d0f
commit 1d61fd3696
19 changed files with 270 additions and 130 deletions

View file

@ -1021,7 +1021,7 @@ pinos_connection_flush (PinosConnection *conn)
} }
while (true) { while (true) {
len = sendmsg (conn->fd, &msg, 0); len = sendmsg (conn->fd, &msg, MSG_NOSIGNAL);
if (len < 0) { if (len < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;

View file

@ -180,6 +180,12 @@ gst_pinos_src_finalize (GObject * object)
g_queue_foreach (&pinossrc->queue, (GFunc) gst_mini_object_unref, NULL); g_queue_foreach (&pinossrc->queue, (GFunc) gst_mini_object_unref, NULL);
g_queue_clear (&pinossrc->queue); 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) if (pinossrc->properties)
gst_structure_free (pinossrc->properties); gst_structure_free (pinossrc->properties);
g_object_unref (pinossrc->fd_allocator); g_object_unref (pinossrc->fd_allocator);
@ -275,6 +281,10 @@ gst_pinos_src_init (GstPinosSrc * src)
src->fd_allocator = gst_fd_allocator_new (); src->fd_allocator = gst_fd_allocator_new ();
src->client_name = pinos_client_name (); 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->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 * static GstCaps *
@ -989,10 +999,6 @@ gst_pinos_src_open (GstPinosSrc * pinossrc)
{ {
PinosProperties *props; 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) if (pinos_thread_main_loop_start (pinossrc->main_loop) != SPA_RESULT_OK)
goto mainloop_failed; goto mainloop_failed;
@ -1052,24 +1058,19 @@ connect_error:
static void static void
gst_pinos_src_close (GstPinosSrc * pinossrc) gst_pinos_src_close (GstPinosSrc * pinossrc)
{ {
clear_queue (pinossrc);
pinos_thread_main_loop_stop (pinossrc->main_loop); 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); pinos_context_destroy (pinossrc->ctx);
pinossrc->ctx = NULL; pinossrc->ctx = NULL;
pinos_loop_destroy (pinossrc->loop);
pinossrc->loop = NULL;
GST_OBJECT_LOCK (pinossrc); GST_OBJECT_LOCK (pinossrc);
g_clear_object (&pinossrc->clock); g_clear_object (&pinossrc->clock);
g_clear_object (&pinossrc->stream);
GST_OBJECT_UNLOCK (pinossrc); GST_OBJECT_UNLOCK (pinossrc);
clear_queue (pinossrc);
if (pinossrc->clock)
gst_object_unref (pinossrc->clock);
pinossrc->clock = NULL;
} }
static GstStateChangeReturn static GstStateChangeReturn

View file

@ -124,15 +124,30 @@ object_new (size_t size,
} }
static void 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) if (this->destroy)
this->destroy (this); this->destroy (this);
free (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 * static PinosProtocolNativeObject *
find_object (PinosProtocolNative *impl, find_object (PinosProtocolNative *impl,
void *object) void *object)
@ -149,8 +164,9 @@ static void
client_destroy (PinosProtocolNativeClient *this) client_destroy (PinosProtocolNativeClient *this)
{ {
spa_list_remove (&this->link); spa_list_remove (&this->link);
pinos_loop_destroy_source (this->parent.impl->core->main_loop->loop, if (this->source)
this->source); pinos_loop_destroy_source (this->parent.impl->core->main_loop->loop,
this->source);
pinos_connection_destroy (this->connection); pinos_connection_destroy (this->connection);
close (this->fd); close (this->fd);
} }
@ -276,6 +292,10 @@ connection_data (SpaSource *source,
size_t size; size_t size;
if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { 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); pinos_client_destroy (client->parent.global->object);
return; return;
} }

View file

@ -1274,14 +1274,15 @@ pinos_client_node_new (PinosClient *client,
} }
static void static void
on_node_remove (PinosNode *node, on_node_remove (void *object,
void *data, void *data,
SpaResult res) SpaResult res,
uint32_t id)
{ {
PinosClientNode *this = data; PinosClientNode *this = object;
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); 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); proxy_clear (&impl->proxy);
if (impl->data_fd != -1) if (impl->data_fd != -1)
@ -1290,24 +1291,21 @@ on_node_remove (PinosNode *node,
} }
SpaResult void
pinos_client_node_destroy (PinosClientNode * this) pinos_client_node_destroy (PinosClientNode * this)
{ {
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this);
SpaResult res;
pinos_log_debug ("client-node %p: destroy", impl); pinos_log_debug ("client-node %p: destroy", impl);
pinos_signal_emit (&this->destroy_signal, this); 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, pinos_main_loop_defer (this->node->core->main_loop,
this->node, this,
res, SPA_RESULT_WAIT_SYNC,
(PinosDeferFunc) on_node_remove, (PinosDeferFunc) on_node_remove,
this); this);
return res;
} }
/** /**

View file

@ -50,7 +50,7 @@ PinosClientNode * pinos_client_node_new (PinosClient *client,
uint32_t id, uint32_t id,
const char *name, const char *name,
PinosProperties *properties); 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); SpaResult pinos_client_node_get_data_socket (PinosClientNode *node, int *fd);

View file

@ -63,32 +63,46 @@ pinos_client_new (PinosCore *core,
return this; 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: * pinos_client_destroy:
* @client: a #PinosClient * @client: a #PinosClient
* *
* Trigger removal of @client * Trigger removal of @client
*/ */
SpaResult void
pinos_client_destroy (PinosClient * client) pinos_client_destroy (PinosClient * client)
{ {
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
PinosResource *resource, *tmp; PinosResource *resource, *tmp;
pinos_log_debug ("client %p: destroy", client); pinos_log_debug ("client %p: destroy", client);
pinos_signal_emit (&client->destroy_signal, client); pinos_signal_emit (&client->destroy_signal, client);
pinos_global_destroy (client->global);
spa_list_for_each_safe (resource, tmp, &client->resource_list, link) spa_list_for_each_safe (resource, tmp, &client->resource_list, link)
pinos_resource_destroy (resource); pinos_resource_destroy (resource);
pinos_global_destroy (client->global);
spa_list_remove (&client->link); spa_list_remove (&client->link);
if (client->properties) pinos_main_loop_defer (client->core->main_loop,
pinos_properties_free (client->properties); client,
SPA_RESULT_WAIT_SYNC,
free (impl); sync_destroy,
client);
return SPA_RESULT_OK;
} }

View file

@ -55,7 +55,7 @@ struct _PinosClient {
PinosClient * pinos_client_new (PinosCore *core, PinosClient * pinos_client_new (PinosCore *core,
PinosProperties *properties); PinosProperties *properties);
SpaResult pinos_client_destroy (PinosClient *client); void pinos_client_destroy (PinosClient *client);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -114,11 +114,24 @@ pinos_core_add_global (PinosCore *core,
return global; 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) pinos_global_destroy (PinosGlobal *global)
{ {
PinosCore *core = global->core; PinosCore *core = global->core;
pinos_log_debug ("global %p: destroy", global);
pinos_signal_emit (&global->destroy_signal, global); pinos_signal_emit (&global->destroy_signal, global);
pinos_map_remove (&core->objects, global->id); pinos_map_remove (&core->objects, global->id);
@ -126,9 +139,11 @@ pinos_global_destroy (PinosGlobal *global)
spa_list_remove (&global->link); spa_list_remove (&global->link);
pinos_signal_emit (&core->global_removed, core, global); pinos_signal_emit (&core->global_removed, core, global);
free (global); pinos_main_loop_defer (core->main_loop,
global,
return SPA_RESULT_OK; SPA_RESULT_WAIT_SYNC,
sync_destroy,
global);
} }
PinosPort * PinosPort *

View file

@ -115,7 +115,7 @@ void pinos_core_destroy (PinosCore *core);
PinosGlobal * pinos_core_add_global (PinosCore *core, PinosGlobal * pinos_core_add_global (PinosCore *core,
uint32_t type, uint32_t type,
void *object); void *object);
SpaResult pinos_global_destroy (PinosGlobal *global); void pinos_global_destroy (PinosGlobal *global);
PinosPort * pinos_core_find_port (PinosCore *core, PinosPort * pinos_core_find_port (PinosCore *core,

View file

@ -154,6 +154,7 @@ again:
asprintf (&error, "error set output format: %d", res); asprintf (&error, "error set output format: %d", res);
goto error; goto error;
} }
pinos_main_loop_defer (this->core->main_loop, this->output->node, res, NULL, NULL);
} else if (in_state == SPA_NODE_STATE_CONFIGURE) { } else if (in_state == SPA_NODE_STATE_CONFIGURE) {
pinos_log_debug ("link %p: doing set format on input", this); pinos_log_debug ("link %p: doing set format on input", this);
if ((res = spa_node_port_set_format (this->input->node->node, if ((res = spa_node_port_set_format (this->input->node->node,
@ -164,6 +165,7 @@ again:
asprintf (&error, "error set input format: %d", res); asprintf (&error, "error set input format: %d", res);
goto error; goto error;
} }
pinos_main_loop_defer (this->core->main_loop, this->input->node, res, NULL, NULL);
} }
return res; return res;
@ -419,6 +421,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
asprintf (&error, "error alloc output buffers: %d", res); asprintf (&error, "error alloc output buffers: %d", res);
goto error; goto error;
} }
pinos_main_loop_defer (this->core->main_loop, this->output->node, res, NULL, NULL);
this->output->buffers = impl->buffers; this->output->buffers = impl->buffers;
this->output->n_buffers = impl->n_buffers; this->output->n_buffers = impl->n_buffers;
this->output->allocated = TRUE; 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); asprintf (&error, "error alloc input buffers: %d", res);
goto error; goto error;
} }
pinos_main_loop_defer (this->core->main_loop, this->input->node, res, NULL, NULL);
this->input->buffers = impl->buffers; this->input->buffers = impl->buffers;
this->input->n_buffers = impl->n_buffers; this->input->n_buffers = impl->n_buffers;
this->input->allocated = TRUE; 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); asprintf (&error, "error use input buffers: %d", res);
goto error; goto error;
} }
pinos_main_loop_defer (this->core->main_loop, this->input->node, res, NULL, NULL);
this->input->buffers = impl->buffers; this->input->buffers = impl->buffers;
this->input->n_buffers = impl->n_buffers; this->input->n_buffers = impl->n_buffers;
this->input->allocated = FALSE; 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); asprintf (&error, "error use output buffers: %d", res);
goto error; goto error;
} }
pinos_main_loop_defer (this->core->main_loop, this->output->node, res, NULL, NULL);
this->output->buffers = impl->buffers; this->output->buffers = impl->buffers;
this->output->n_buffers = impl->n_buffers; this->output->n_buffers = impl->n_buffers;
this->output->allocated = FALSE; this->output->allocated = FALSE;
@ -519,11 +525,6 @@ check_states (PinosLink *this,
{ {
SpaNodeState in_state, out_state; SpaNodeState in_state, out_state;
if (res != SPA_RESULT_OK) {
pinos_log_warn ("link %p: error: %d", this, res);
return res;
}
again: again:
if (this->input == NULL || this->output == NULL) if (this->input == NULL || this->output == NULL)
return SPA_RESULT_OK; return SPA_RESULT_OK;
@ -550,7 +551,11 @@ again:
return SPA_RESULT_OK; return SPA_RESULT_OK;
exit: 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; return res;
} }
@ -740,7 +745,6 @@ do_link_remove_done (SpaLoop *loop,
void *user_data) void *user_data)
{ {
PinosLink *this = user_data; PinosLink *this = user_data;
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
if (this->input) { if (this->input) {
spa_list_remove (&this->input_link); spa_list_remove (&this->input_link);
@ -765,12 +769,10 @@ do_link_remove_done (SpaLoop *loop,
this->output = NULL; this->output = NULL;
} }
pinos_main_loop_defer_cancel (this->core->main_loop, this, 0); pinos_main_loop_defer_complete (this->core->main_loop,
this,
if (impl->allocated) seq,
pinos_memblock_free (&impl->buffer_mem); SPA_RESULT_OK);
free (impl);
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -804,13 +806,29 @@ do_link_remove (SpaLoop *loop,
return res; 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: * pinos_link_destroy:
* @link: a #PinosLink * @link: a #PinosLink
* *
* Trigger removal of @link * Trigger removal of @link
*/ */
SpaResult void
pinos_link_destroy (PinosLink * this) pinos_link_destroy (PinosLink * this)
{ {
SpaResult res = SPA_RESULT_OK; SpaResult res = SPA_RESULT_OK;
@ -832,6 +850,8 @@ pinos_link_destroy (PinosLink * this)
0, 0,
NULL, NULL,
this); this);
pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL);
} }
if (this->output) { if (this->output) {
pinos_signal_remove (&impl->output_port_destroy); pinos_signal_remove (&impl->output_port_destroy);
@ -843,6 +863,12 @@ pinos_link_destroy (PinosLink * this)
0, 0,
NULL, NULL,
this); 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);
} }

View file

@ -79,7 +79,7 @@ PinosLink * pinos_link_new (PinosCore *core,
PinosPort *input, PinosPort *input,
SpaFormat **format_filter, SpaFormat **format_filter,
PinosProperties *properties); PinosProperties *properties);
SpaResult pinos_link_destroy (PinosLink *link); void pinos_link_destroy (PinosLink *link);
bool pinos_link_activate (PinosLink *link); bool pinos_link_activate (PinosLink *link);
bool pinos_link_deactivate (PinosLink *link); bool pinos_link_deactivate (PinosLink *link);

View file

@ -64,8 +64,15 @@ process_work_queue (SpaSource *source,
WorkItem *item, *tmp; WorkItem *item, *tmp;
spa_list_for_each_safe (item, tmp, &impl->work_list, link) { 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; 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); spa_list_remove (&item->link);
@ -78,11 +85,11 @@ process_work_queue (SpaSource *source,
} }
static uint32_t static uint32_t
do_add_work (PinosMainLoop *loop, main_loop_defer (PinosMainLoop *loop,
void *obj, void *obj,
SpaResult res, SpaResult res,
PinosDeferFunc func, PinosDeferFunc func,
void *data) void *data)
{ {
PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this);
WorkItem *item; WorkItem *item;
@ -103,6 +110,11 @@ do_add_work (PinosMainLoop *loop,
item->seq = SPA_RESULT_ASYNC_SEQ (res); item->seq = SPA_RESULT_ASYNC_SEQ (res);
item->res = res; item->res = res;
pinos_log_debug ("main-loop %p: defer async %d for object %p", loop, item->seq, obj); 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 { } else {
item->seq = SPA_ID_INVALID; item->seq = SPA_ID_INVALID;
item->res = res; item->res = res;
@ -117,16 +129,6 @@ do_add_work (PinosMainLoop *loop,
return item->id; 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 static void
main_loop_defer_cancel (PinosMainLoop *loop, main_loop_defer_cancel (PinosMainLoop *loop,
void *obj, void *obj,
@ -175,28 +177,6 @@ main_loop_defer_complete (PinosMainLoop *loop,
return have_work; 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: * pinos_main_loop_new:
@ -223,8 +203,6 @@ pinos_main_loop_new (void)
process_work_queue, process_work_queue,
impl); impl);
this->run = main_loop_run;
this->quit = main_loop_quit;
this->defer = main_loop_defer; this->defer = main_loop_defer;
this->defer_cancel = main_loop_defer_cancel; this->defer_cancel = main_loop_defer_cancel;
this->defer_complete = main_loop_defer_complete; this->defer_complete = main_loop_defer_complete;
@ -251,3 +229,26 @@ pinos_main_loop_destroy (PinosMainLoop *loop)
free (item); free (item);
free (impl); 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);
}

View file

@ -45,9 +45,6 @@ struct _PinosMainLoop {
PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosMainLoop *loop)); PinosMainLoop *loop));
void (*run) (PinosMainLoop *loop);
void (*quit) (PinosMainLoop *loop);
uint32_t (*defer) (PinosMainLoop *loop, uint32_t (*defer) (PinosMainLoop *loop,
void *obj, void *obj,
SpaResult res, SpaResult res,
@ -65,13 +62,12 @@ struct _PinosMainLoop {
PinosMainLoop * pinos_main_loop_new (void); PinosMainLoop * pinos_main_loop_new (void);
void pinos_main_loop_destroy (PinosMainLoop *loop); void pinos_main_loop_destroy (PinosMainLoop *loop);
#define pinos_main_loop_run(m) (m)->run(m) void pinos_main_loop_run (PinosMainLoop *loop);
#define pinos_main_loop_quit(m) (m)->quit(m) void pinos_main_loop_quit (PinosMainLoop *loop);
#define pinos_main_loop_defer(m,...) (m)->defer(m,__VA_ARGS__) #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_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_defer_complete(m,...) (m)->defer_complete(m,__VA_ARGS__)
#define pinos_main_loop_sync(m,...) (m)->sync(m,__VA_ARGS__)
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -477,22 +477,19 @@ do_node_remove_done (SpaLoop *loop,
void *user_data) void *user_data)
{ {
PinosNode *this = user_data; PinosNode *this = user_data;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
PinosPort *port, *tmp; 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) spa_list_for_each_safe (port, tmp, &this->input_ports, link)
pinos_port_destroy (port); pinos_port_destroy (port);
spa_list_for_each_safe (port, tmp, &this->output_ports, link) spa_list_for_each_safe (port, tmp, &this->output_ports, link)
pinos_port_destroy (port); pinos_port_destroy (port);
free (this->name); pinos_main_loop_defer_complete (this->core->main_loop,
free (this->error); this,
if (this->properties) seq,
pinos_properties_free (this->properties); SPA_RESULT_OK);
free (impl);
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -536,6 +533,24 @@ do_node_remove (SpaLoop *loop,
return res; 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: * pinos_node_destroy:
* @node: a #PinosNode * @node: a #PinosNode
@ -543,7 +558,7 @@ do_node_remove (SpaLoop *loop,
* Remove @node. This will stop the transfer on the node and * Remove @node. This will stop the transfer on the node and
* free the resources allocated by @node. * free the resources allocated by @node.
*/ */
SpaResult void
pinos_node_destroy (PinosNode * this) pinos_node_destroy (PinosNode * this)
{ {
SpaResult res; SpaResult res;
@ -561,7 +576,18 @@ pinos_node_destroy (PinosNode * this)
0, 0,
NULL, NULL,
this); 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);
} }
/** /**

View file

@ -94,7 +94,7 @@ PinosNode * pinos_node_new (PinosCore *core,
SpaNode *node, SpaNode *node,
SpaClock *clock, SpaClock *clock,
PinosProperties *properties); PinosProperties *properties);
SpaResult pinos_node_destroy (PinosNode *node); void pinos_node_destroy (PinosNode *node);
void pinos_node_set_data_loop (PinosNode *node, void pinos_node_set_data_loop (PinosNode *node,

View file

@ -54,6 +54,17 @@ pinos_port_new (PinosNode *node,
return this; return this;
} }
static void
sync_destroy (void *object,
void *data,
SpaResult res,
uint32_t id)
{
PinosPort *port = object;
free (port);
}
void void
pinos_port_destroy (PinosPort *port) pinos_port_destroy (PinosPort *port)
{ {
@ -61,6 +72,8 @@ pinos_port_destroy (PinosPort *port)
pinos_signal_emit (&port->destroy_signal, port); pinos_signal_emit (&port->destroy_signal, port);
spa_list_remove (&port->link);
spa_node_port_use_buffers (port->node->node, spa_node_port_use_buffers (port->node->node,
port->direction, port->direction,
port->port_id, port->port_id,
@ -68,8 +81,11 @@ pinos_port_destroy (PinosPort *port)
port->buffers = NULL; port->buffers = NULL;
port->n_buffers = 0; port->n_buffers = 0;
spa_list_remove (&port->link); pinos_main_loop_defer (port->node->core->main_loop,
free (port); port,
SPA_RESULT_WAIT_SYNC,
sync_destroy,
port);
} }
static SpaResult static SpaResult

View file

@ -50,6 +50,17 @@ pinos_resource_new (PinosClient *client,
return resource; 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 SpaResult
pinos_resource_destroy (PinosResource *resource) pinos_resource_destroy (PinosResource *resource)
{ {
@ -61,7 +72,11 @@ pinos_resource_destroy (PinosResource *resource)
if (resource->destroy) if (resource->destroy)
resource->destroy (resource->object); 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; return SPA_RESULT_OK;
} }

View file

@ -32,6 +32,7 @@ extern "C" {
typedef enum { typedef enum {
SPA_RESULT_ASYNC = (1 << 30), SPA_RESULT_ASYNC = (1 << 30),
SPA_RESULT_WAIT_SYNC = 2,
SPA_RESULT_MODIFIED = 1, SPA_RESULT_MODIFIED = 1,
SPA_RESULT_OK = 0, SPA_RESULT_OK = 0,
SPA_RESULT_ERROR = -1, SPA_RESULT_ERROR = -1,

View file

@ -40,16 +40,27 @@ struct _SpaDict {
SpaDictItem *items; 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 * static inline const char *
spa_dict_lookup (const SpaDict *dict, const char *key) spa_dict_lookup (const SpaDict *dict, const char *key)
{ {
unsigned int i; SpaDictItem *item = spa_dict_lookup_item (dict, key);
return item ? item->value : NULL;
for (i = 0; i < dict->n_items; i++) {
if (!strcmp (dict->items[i].key, key))
return dict->items[i].value;
}
return NULL;
} }
#ifdef __cplusplus #ifdef __cplusplus