track client resources

This commit is contained in:
Wim Taymans 2016-11-15 17:06:09 +01:00
parent 0d21d633c9
commit b6ad45bb74
14 changed files with 253 additions and 92 deletions

View file

@ -1274,7 +1274,6 @@ proxy_clear (SpaProxy *this)
/**
* pinos_client_node_new:
* @daemon: a #PinosDaemon
* @client: the client owner
* @name: a name
* @properties: extra properties
*
@ -1284,7 +1283,6 @@ proxy_clear (SpaProxy *this)
*/
PinosClientNode *
pinos_client_node_new (PinosCore *core,
PinosClient *client,
const gchar *name,
PinosProperties *properties)
{
@ -1323,16 +1321,15 @@ pinos_client_node_new (PinosCore *core,
return this;
}
void
pinos_client_node_destroy (PinosClientNode * this)
static void
on_node_remove (PinosNode *node,
gpointer data,
SpaResult res)
{
PinosClientNode *this = data;
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this);
pinos_log_debug ("client-node %p: destroy", impl);
pinos_signal_emit (&this->destroy_signal, this);
pinos_node_destroy (this->node);
pinos_log_debug ("client-node %p: finalize", node);
proxy_clear (&impl->proxy);
if (impl->ctrl_fd != -1)
@ -1342,6 +1339,27 @@ pinos_client_node_destroy (PinosClientNode * this)
free (impl);
}
SpaResult
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_main_loop_defer (this->node->core->main_loop,
this->node,
res,
(PinosDeferFunc) on_node_remove,
this);
return res;
}
/**
* pinos_client_node_get_ctrl_socket:
* @node: a #PinosClientNode

View file

@ -26,6 +26,9 @@
extern "C" {
#endif
#define PINOS_CLIENT_NODE_URI "http://pinos.org/ns/client-node"
#define PINOS_CLIENT_NODE_PREFIX PINOS_CLIENT_NODE_URI "#"
typedef struct _PinosClientNode PinosClientNode;
/**
@ -41,10 +44,9 @@ struct _PinosClientNode {
};
PinosClientNode * pinos_client_node_new (PinosCore *core,
PinosClient *client,
const gchar *name,
PinosProperties *properties);
void pinos_client_node_destroy (PinosClientNode *node);
SpaResult pinos_client_node_destroy (PinosClientNode *node);
SpaResult pinos_client_node_get_ctrl_socket (PinosClientNode *node, int *fd);
SpaResult pinos_client_node_get_data_socket (PinosClientNode *node, int *fd);

View file

@ -31,7 +31,6 @@ typedef struct
guint id;
PinosClient1 *iface;
GList *objects;
} PinosClientImpl;
static void
@ -86,44 +85,50 @@ client_watch_name (PinosClient *this)
(GDestroyNotify) pinos_client_destroy);
}
void
pinos_client_add_object (PinosClient *client,
PinosObject *object)
PinosResource *
pinos_client_add_resource (PinosClient *client,
uint32_t type,
void *object,
PinosDestroy destroy)
{
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
PinosResource *resource;
g_return_if_fail (client);
g_return_if_fail (object);
resource = calloc (1, sizeof (PinosResource));
resource->core = client->core;
resource->id = 0;
resource->type = type;
resource->object = object;
resource->destroy = destroy;
impl->objects = g_list_prepend (impl->objects, object);
pinos_signal_init (&resource->destroy_signal);
pinos_log_debug ("client %p: add resource %p", client, resource);
spa_list_insert (client->resource_list.prev, &resource->link);
return resource;
}
void
pinos_client_remove_object (PinosClient *client,
PinosObject *object)
pinos_client_remove_resource (PinosClient *client,
PinosResource *resource)
{
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
pinos_log_debug ("client %p: resource %p destroy", client, resource);
pinos_signal_emit (&resource->destroy_signal, resource);
g_return_if_fail (client);
g_return_if_fail (object);
spa_list_remove (&resource->link);
impl->objects = g_list_remove (impl->objects, object);
pinos_object_destroy (object);
if (resource->destroy)
resource->destroy (resource->object);
free (resource);
}
bool
pinos_client_has_object (PinosClient *client,
PinosObject *object)
pinos_client_has_resource (PinosClient *client,
PinosResource *resource)
{
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
GList *found;
g_return_val_if_fail (client, false);
g_return_val_if_fail (object, false);
found = g_list_find (impl->objects, object);
return found != NULL;
return false;
}
/**
@ -153,6 +158,7 @@ pinos_client_new (PinosCore *core,
this->sender = strdup (sender);
this->properties = properties;
spa_list_init (&this->resource_list);
pinos_signal_init (&this->destroy_signal);
impl->iface = pinos_client1_skeleton_new ();
@ -170,20 +176,19 @@ pinos_client_new (PinosCore *core,
*
* Trigger removal of @client
*/
void
SpaResult
pinos_client_destroy (PinosClient * client)
{
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
GList *copy;
PinosResource *resource, *tmp;
pinos_log_debug ("client %p: destroy", client);
pinos_signal_emit (&client->destroy_signal, client);
spa_list_remove (&client->list);
spa_list_for_each_safe (resource, tmp, &client->resource_list, link)
pinos_client_remove_resource (client, resource);
copy = g_list_copy (impl->objects);
g_list_free_full (copy, NULL);
g_list_free (impl->objects);
spa_list_remove (&client->list);
free (client->sender);
if (client->properties)
@ -191,4 +196,6 @@ pinos_client_destroy (PinosClient * client)
g_clear_object (&impl->iface);
free (impl);
return SPA_RESULT_OK;
}

View file

@ -28,10 +28,25 @@ extern "C" {
#define PINOS_CLIENT_PREFIX PINOS_CLIENT_URI "#"
typedef struct _PinosClient PinosClient;
typedef struct _PinosResource PinosResource;
typedef void (*PinosDestroy) (void *object);
#include <pinos/client/object.h>
#include <pinos/server/daemon.h>
struct _PinosResource {
PinosCore *core;
SpaList link;
uint32_t id;
uint32_t type;
void *object;
PinosDestroy destroy;
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosResource *resource));
};
/**
* PinosClient:
*
@ -45,6 +60,8 @@ struct _PinosClient {
char *sender;
PinosProperties *properties;
SpaList resource_list;
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosClient *client));
};
@ -52,15 +69,18 @@ struct _PinosClient {
PinosClient * pinos_client_new (PinosCore *core,
const gchar *sender,
PinosProperties *properties);
void pinos_client_destroy (PinosClient *client);
SpaResult pinos_client_destroy (PinosClient *client);
void pinos_client_add_object (PinosClient *client,
PinosObject *object);
void pinos_client_remove_object (PinosClient *client,
PinosObject *object);
bool pinos_client_has_object (PinosClient *client,
PinosObject *object);
PinosResource * pinos_client_add_resource (PinosClient *client,
uint32_t type,
void *object,
PinosDestroy destroy);
void pinos_client_remove_resource (PinosClient *client,
PinosResource *resource);
bool pinos_client_has_resource (PinosClient *client,
PinosResource *resource);
#ifdef __cplusplus
}

View file

@ -98,7 +98,9 @@ pinos_core_add_global (PinosCore *core,
global->object = object;
global->skel = skel;
spa_list_insert (core->global_list.prev, &global->list);
pinos_signal_init (&global->destroy_signal);
spa_list_insert (core->global_list.prev, &global->link);
pinos_signal_emit (&core->global_added, core, global);
return global;
@ -108,8 +110,10 @@ void
pinos_core_remove_global (PinosCore *core,
PinosGlobal *global)
{
pinos_signal_emit (&global->destroy_signal, global);
spa_list_remove (&global->link);
pinos_signal_emit (&core->global_removed, core, global);
spa_list_remove (&global->list);
free (global);
}

View file

@ -40,11 +40,14 @@ typedef struct _PinosGlobal PinosGlobal;
struct _PinosGlobal {
PinosCore *core;
SpaList list;
SpaList link;
uint32_t id;
uint32_t type;
void *object;
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosGlobal *global));
PinosObjectSkeleton *skel;
const char *object_path;
};
@ -74,7 +77,6 @@ struct _PinosCore {
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosCore *core));
PINOS_SIGNAL (global_added, (PinosListener *listener,
PinosCore *core,
PinosGlobal *global));

View file

@ -343,7 +343,6 @@ handle_create_client_node (PinosDaemon1 *interface,
props = pinos_properties_from_variant (arg_properties);
node = pinos_client_node_new (this->core,
client,
arg_name,
props);
@ -353,7 +352,10 @@ handle_create_client_node (PinosDaemon1 *interface,
if ((res = pinos_client_node_get_data_socket (node, &data_fd)) < 0)
goto no_socket;
//pinos_client_add_object (client, &node->object);
pinos_client_add_resource (client,
this->core->registry.uri.client_node,
node,
(PinosDestroy) pinos_client_node_destroy);
object_path = node->node->global->object_path;
pinos_log_debug ("daemon %p: add client-node %p, %s", impl, node, object_path);

View file

@ -42,6 +42,8 @@ typedef struct
PinosLink1 *iface;
uint32_t seq;
SpaFormat **format_filter;
PinosProperties *properties;
@ -622,8 +624,11 @@ on_port_unlinked (PinosPort *port, PinosLink *this, SpaResult res, gulong id)
{
pinos_signal_emit (&this->core->port_unlinked, this, port);
if (this->input == NULL || this->output == NULL)
if (this->input == NULL || this->output == NULL) {
pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED);
pinos_link_destroy (this);
}
}
static void
@ -636,10 +641,14 @@ on_port_destroy (PinosLink *this,
if (port == this->input) {
pinos_log_debug ("link %p: input port destroyed %p", this, port);
pinos_signal_remove (&impl->input_port_destroy);
pinos_signal_remove (&impl->input_async_complete);
this->input = NULL;
other = this->output;
} else if (port == this->output) {
pinos_log_debug ("link %p: output port destroyed %p", this, port);
pinos_signal_remove (&impl->output_port_destroy);
pinos_signal_remove (&impl->output_async_complete);
this->output = NULL;
other = this->input;
} else
@ -667,7 +676,6 @@ on_input_port_destroy (PinosListener *listener,
PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, input_port_destroy);
on_port_destroy (&impl->this, port);
pinos_signal_remove (listener);
}
static void
@ -725,14 +733,14 @@ pinos_link_new (PinosCore *core,
&impl->input_port_destroy,
on_input_port_destroy);
pinos_signal_add (&this->output->destroy_signal,
&impl->output_port_destroy,
on_output_port_destroy);
pinos_signal_add (&this->input->node->async_complete,
&impl->input_async_complete,
on_input_async_complete_notify);
pinos_signal_add (&this->output->destroy_signal,
&impl->output_port_destroy,
on_output_port_destroy);
pinos_signal_add (&this->output->node->async_complete,
&impl->output_async_complete,
on_output_async_complete_notify);
@ -754,38 +762,134 @@ pinos_link_new (PinosCore *core,
return this;
}
/**
* pinos_link_destroy:
* @link: a #PinosLink
*
* Trigger removal of @link
*/
void
pinos_link_destroy (PinosLink * this)
static void
clear_port_buffers (PinosLink *link, PinosPort *port)
{
if (!port->allocated) {
pinos_log_debug ("link %p: clear buffers on port %p", link, port);
spa_node_port_use_buffers (port->node->node,
port->direction,
port->port_id,
NULL, 0);
port->buffers = NULL;
port->n_buffers = 0;
}
}
static SpaResult
do_link_remove_done (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
PinosLink *this = user_data;
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
pinos_log_debug ("link %p: destroy", impl);
pinos_signal_emit (&this->destroy_signal, this);
if (this->input) {
pinos_signal_remove (&impl->input_port_destroy);
pinos_signal_remove (&impl->input_async_complete);
spa_list_remove (&this->input_link);
this->input->node->n_used_input_links--;
if (this->input->node->n_used_input_links == 0 &&
this->input->node->n_used_output_links == 0)
pinos_node_report_idle (this->input->node);
clear_port_buffers (this, this->input);
this->input = NULL;
}
if (this->output) {
pinos_signal_remove (&impl->output_port_destroy);
pinos_signal_remove (&impl->output_async_complete);
spa_list_remove (&this->output_link);
this->output->node->n_used_output_links--;
if (this->output->node->n_used_input_links == 0 &&
this->output->node->n_used_output_links == 0)
pinos_node_report_idle (this->output->node);
clear_port_buffers (this, this->output);
this->output = NULL;
}
pinos_main_loop_defer_cancel (this->core->main_loop, this, 0);
pinos_core_remove_global (this->core, this->global);
spa_list_remove (&this->list);
g_clear_object (&impl->iface);
if (impl->allocated)
pinos_memblock_free (&impl->buffer_mem);
free (impl);
return SPA_RESULT_OK;
}
static SpaResult
do_link_remove (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
SpaResult res;
PinosLink *this = user_data;
if (this->rt.input) {
spa_list_remove (&this->rt.input_link);
this->rt.input = NULL;
}
if (this->rt.output) {
spa_list_remove (&this->rt.output_link);
this->rt.output = NULL;
}
res = spa_poll_invoke (this->core->main_loop->poll,
do_link_remove_done,
seq,
0,
NULL,
this);
return res;
}
/**
* pinos_link_destroy:
* @link: a #PinosLink
*
* Trigger removal of @link
*/
SpaResult
pinos_link_destroy (PinosLink * this)
{
SpaResult res = SPA_RESULT_OK;
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
pinos_log_debug ("link %p: destroy", impl);
pinos_signal_emit (&this->destroy_signal, this);
pinos_core_remove_global (this->core, this->global);
spa_list_remove (&this->list);
if (this->input) {
pinos_signal_remove (&impl->input_port_destroy);
pinos_signal_remove (&impl->input_async_complete);
res = spa_poll_invoke (&this->input->node->data_loop->poll,
do_link_remove,
impl->seq++,
0,
NULL,
this);
}
if (this->output) {
pinos_signal_remove (&impl->output_port_destroy);
pinos_signal_remove (&impl->output_async_complete);
res = spa_poll_invoke (&this->output->node->data_loop->poll,
do_link_remove,
impl->seq++,
0,
NULL,
this);
}
return res;
}

View file

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

View file

@ -225,9 +225,7 @@ process_work_queue (PinosMainLoop *this)
impl->work_id = 0;
pinos_log_debug ("main-loop %p: %p %p", this, impl->work_list.next, &impl->work_list);
spa_list_for_each_safe (item, tmp, &impl->work_list, link) {
pinos_log_debug ("main-loop %p: %p %p %d %p", this, &item->link, impl->work_list.next, item->sync, item->obj);
if (item->sync) {
if (&item->link == impl->work_list.next) {
pinos_log_debug ("main-loop %p: found sync item %p", this, item->obj);

View file

@ -399,7 +399,6 @@ handle_remove (PinosNode1 *interface,
PinosNode *this = user_data;
pinos_log_debug ("node %p: remove", this);
pinos_node_destroy (this);
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("()"));
@ -585,9 +584,10 @@ do_node_remove (SpaPoll *poll,
* Remove @node. This will stop the transfer on the node and
* free the resources allocated by @node.
*/
void
SpaResult
pinos_node_destroy (PinosNode * this)
{
SpaResult res;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
pinos_log_debug ("node %p: destroy", impl);
@ -596,12 +596,13 @@ pinos_node_destroy (PinosNode * this)
spa_list_remove (&this->list);
pinos_core_remove_global (this->core, this->global);
spa_poll_invoke (&this->data_loop->poll,
res = spa_poll_invoke (&this->data_loop->poll,
do_node_remove,
impl->seq++,
0,
NULL,
this);
return res;
}
/**

View file

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

View file

@ -26,6 +26,7 @@
#include "pinos/server/node.h"
#include "pinos/server/node-factory.h"
#include "pinos/server/client.h"
#include "pinos/server/client-node.h"
#include "spa/include/spa/monitor.h"
@ -40,6 +41,7 @@ pinos_registry_init (PinosRegistry *reg)
reg->uri.node_factory = spa_id_map_get_id (reg->map, PINOS_NODE_FACTORY_URI);
reg->uri.link = spa_id_map_get_id (reg->map, PINOS_LINK_URI);
reg->uri.client = spa_id_map_get_id (reg->map, PINOS_CLIENT_URI);
reg->uri.client_node = spa_id_map_get_id (reg->map, PINOS_CLIENT_NODE_URI);
reg->uri.spa_node = spa_id_map_get_id (reg->map, SPA_NODE_URI);
reg->uri.spa_clock = spa_id_map_get_id (reg->map, SPA_CLOCK_URI);

View file

@ -41,6 +41,7 @@ typedef struct {
uint32_t node_factory;
uint32_t link;
uint32_t client;
uint32_t client_node;
uint32_t spa_node;
uint32_t spa_clock;