Before this patch, when you add a "port added" listener to a graph,
you can pass a callback which gets called when the listener is removed.
This only happens when the graph is destroyed.
This "listener removed" callback feature seems unnecessary as the graph
user, who adds the "port added" listener, has total control over the
graph object. Therefore she can ensure that anything needed by her "port
added" listeners exists as long as the graph exists.
Therefore this patch removes those parameters and everything related.
In Python, we used to keep a strong reference on the partial Python
object (listener's data) and release it when our "listener removed"
function was called. Now, the listener's data is a weak reference, but
we keep a list of strong partial references within the graph object
itself (`self._listener_partials`) to ensure that the partials exist as
long as the graph exists.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: I4c06ff139740f887ae2ace7633d2edeb01fd2fa0
Reviewed-on: https://review.lttng.org/c/babeltrace/+/2637
Tested-by: jenkins <jenkins@lttng.org>
const bt_port_output *upstream_port,
const bt_port_input *downstream_port, void *data);
const bt_port_output *upstream_port,
const bt_port_input *downstream_port, void *data);
-typedef void (* bt_graph_listener_removed_func)(void *data);
-
typedef enum bt_graph_simple_sink_component_initialize_func_status {
BT_GRAPH_SIMPLE_SINK_COMPONENT_INITIALIZE_FUNC_STATUS_OK = __BT_FUNC_STATUS_OK,
BT_GRAPH_SIMPLE_SINK_COMPONENT_INITIALIZE_FUNC_STATUS_ERROR = __BT_FUNC_STATUS_ERROR,
typedef enum bt_graph_simple_sink_component_initialize_func_status {
BT_GRAPH_SIMPLE_SINK_COMPONENT_INITIALIZE_FUNC_STATUS_OK = __BT_FUNC_STATUS_OK,
BT_GRAPH_SIMPLE_SINK_COMPONENT_INITIALIZE_FUNC_STATUS_ERROR = __BT_FUNC_STATUS_ERROR,
bt_graph_add_filter_component_input_port_added_listener(
bt_graph *graph,
bt_graph_filter_component_input_port_added_listener_func listener,
bt_graph_add_filter_component_input_port_added_listener(
bt_graph *graph,
bt_graph_filter_component_input_port_added_listener_func listener,
- bt_graph_listener_removed_func listener_removed, void *data,
- bt_listener_id *listener_id);
+ void *data, bt_listener_id *listener_id);
extern bt_graph_add_listener_status
bt_graph_add_sink_component_input_port_added_listener(
bt_graph *graph,
bt_graph_sink_component_input_port_added_listener_func listener,
extern bt_graph_add_listener_status
bt_graph_add_sink_component_input_port_added_listener(
bt_graph *graph,
bt_graph_sink_component_input_port_added_listener_func listener,
- bt_graph_listener_removed_func listener_removed, void *data,
- bt_listener_id *listener_id);
+ void *data, bt_listener_id *listener_id);
extern bt_graph_add_listener_status
bt_graph_add_source_component_output_port_added_listener(
bt_graph *graph,
bt_graph_source_component_output_port_added_listener_func listener,
extern bt_graph_add_listener_status
bt_graph_add_source_component_output_port_added_listener(
bt_graph *graph,
bt_graph_source_component_output_port_added_listener_func listener,
- bt_graph_listener_removed_func listener_removed, void *data,
- bt_listener_id *listener_id);
+ void *data, bt_listener_id *listener_id);
extern bt_graph_add_listener_status
bt_graph_add_filter_component_output_port_added_listener(
bt_graph *graph,
bt_graph_filter_component_output_port_added_listener_func listener,
extern bt_graph_add_listener_status
bt_graph_add_filter_component_output_port_added_listener(
bt_graph *graph,
bt_graph_filter_component_output_port_added_listener_func listener,
- bt_graph_listener_removed_func listener_removed, void *data,
- bt_listener_id *listener_id);
+ void *data, bt_listener_id *listener_id);
typedef enum bt_graph_add_interrupter_status {
BT_GRAPH_ADD_INTERRUPTER_STATUS_OK = __BT_FUNC_STATUS_OK,
typedef enum bt_graph_add_interrupter_status {
BT_GRAPH_ADD_INTERRUPTER_STATUS_OK = __BT_FUNC_STATUS_OK,
+ # list of listener partials to keep a reference as long as
+ # this graph exists
+ self._listener_partials = []
+
def add_component(
self,
component_class,
def add_component(
self,
component_class,
if listener_ids is None:
raise bt2._Error('cannot add listener to graph object')
if listener_ids is None:
raise bt2._Error('cannot add listener to graph object')
+ # keep the partial's reference
+ self._listener_partials.append(listener_from_native)
+
def run_once(self):
status = native_bt.graph_run_once(self._ptr)
utils._handle_func_status(status, 'graph object could not run once')
def run_once(self):
status = native_bt.graph_run_once(self._ptr)
utils._handle_func_status(status, 'graph object could not run once')
-static
-void graph_listener_removed(void *py_callable)
-{
- BT_ASSERT(py_callable);
- Py_DECREF(py_callable);
-}
-
static bt_graph_listener_func_status port_added_listener(
const void *component,
swig_type_info *component_swig_type,
static bt_graph_listener_func_status port_added_listener(
const void *component,
swig_type_info *component_swig_type,
/* source output port */
status = bt_graph_add_source_component_output_port_added_listener(
graph, source_component_output_port_added_listener,
/* source output port */
status = bt_graph_add_source_component_output_port_added_listener(
graph, source_component_output_port_added_listener,
- graph_listener_removed, py_callable, &listener_id);
+ py_callable, &listener_id);
if (status != __BT_FUNC_STATUS_OK) {
/*
* bt_graph_add_source_component_output_port_added_listener has
if (status != __BT_FUNC_STATUS_OK) {
/*
* bt_graph_add_source_component_output_port_added_listener has
/* filter input port */
status = bt_graph_add_filter_component_input_port_added_listener(
graph, filter_component_input_port_added_listener,
/* filter input port */
status = bt_graph_add_filter_component_input_port_added_listener(
graph, filter_component_input_port_added_listener,
- graph_listener_removed, py_callable, &listener_id);
+ py_callable, &listener_id);
if (status != __BT_FUNC_STATUS_OK) {
/*
* bt_graph_add_filter_component_input_port_added_listener has
if (status != __BT_FUNC_STATUS_OK) {
/*
* bt_graph_add_filter_component_input_port_added_listener has
/* filter output port */
status = bt_graph_add_filter_component_output_port_added_listener(
graph, filter_component_output_port_added_listener,
/* filter output port */
status = bt_graph_add_filter_component_output_port_added_listener(
graph, filter_component_output_port_added_listener,
- graph_listener_removed, py_callable, &listener_id);
+ py_callable, &listener_id);
if (status != __BT_FUNC_STATUS_OK) {
/*
* bt_graph_add_filter_component_output_port_added_listener has
if (status != __BT_FUNC_STATUS_OK) {
/*
* bt_graph_add_filter_component_output_port_added_listener has
/* sink input port */
status = bt_graph_add_sink_component_input_port_added_listener(
graph, sink_component_input_port_added_listener,
/* sink input port */
status = bt_graph_add_sink_component_input_port_added_listener(
graph, sink_component_input_port_added_listener,
- graph_listener_removed, py_callable, &listener_id);
+ py_callable, &listener_id);
if (status != __BT_FUNC_STATUS_OK) {
/*
* bt_graph_add_sink_component_input_port_added_listener has
if (status != __BT_FUNC_STATUS_OK) {
/*
* bt_graph_add_sink_component_input_port_added_listener has
PyTuple_SET_ITEM(py_listener_ids, 3, py_listener_id);
py_listener_id = NULL;
PyTuple_SET_ITEM(py_listener_ids, 3, py_listener_id);
py_listener_id = NULL;
-
- Py_INCREF(py_callable);
- Py_INCREF(py_callable);
- Py_INCREF(py_callable);
- Py_INCREF(py_callable);
-
bt_graph_add_interrupter(ctx->graph, the_interrupter);
add_listener_status = bt_graph_add_source_component_output_port_added_listener(
bt_graph_add_interrupter(ctx->graph, the_interrupter);
add_listener_status = bt_graph_add_source_component_output_port_added_listener(
- ctx->graph, graph_source_output_port_added_listener, NULL, ctx,
+ ctx->graph, graph_source_output_port_added_listener, ctx,
NULL);
if (add_listener_status != BT_GRAPH_ADD_LISTENER_STATUS_OK) {
BT_CLI_LOGE_APPEND_CAUSE(
NULL);
if (add_listener_status != BT_GRAPH_ADD_LISTENER_STATUS_OK) {
BT_CLI_LOGE_APPEND_CAUSE(
}
add_listener_status = bt_graph_add_filter_component_output_port_added_listener(
}
add_listener_status = bt_graph_add_filter_component_output_port_added_listener(
- ctx->graph, graph_filter_output_port_added_listener, NULL, ctx,
+ ctx->graph, graph_filter_output_port_added_listener, ctx,
NULL);
if (add_listener_status != BT_GRAPH_ADD_LISTENER_STATUS_OK) {
BT_CLI_LOGE_APPEND_CAUSE(
NULL);
if (add_listener_status != BT_GRAPH_ADD_LISTENER_STATUS_OK) {
BT_CLI_LOGE_APPEND_CAUSE(
typedef enum bt_component_class_initialize_method_status
(*comp_init_method_t)(const void *, void *, const void *, void *);
typedef enum bt_component_class_initialize_method_status
(*comp_init_method_t)(const void *, void *, const void *, void *);
-struct bt_graph_listener {
- bt_graph_listener_removed_func removed;
- void *data;
-};
-
struct bt_graph_listener_port_added {
struct bt_graph_listener_port_added {
- struct bt_graph_listener base;
};
#define INIT_LISTENERS_ARRAY(_type, _listeners) \
};
#define INIT_LISTENERS_ARRAY(_type, _listeners) \
-#define CALL_REMOVE_LISTENERS(_type, _listeners) \
- do { \
- size_t i; \
- \
- if (!_listeners) { \
- break; \
- } \
- for (i = 0; i < (_listeners)->len; i++) { \
- _type *listener = \
- &g_array_index((_listeners), _type, i); \
- \
- if (listener->base.removed) { \
- listener->base.removed(listener->base.data); \
- } \
- } \
- } while (0)
-
static
void destroy_graph(struct bt_object *obj)
{
static
void destroy_graph(struct bt_object *obj)
{
obj->ref_count++;
graph->config_state = BT_GRAPH_CONFIGURATION_STATE_DESTROYING;
obj->ref_count++;
graph->config_state = BT_GRAPH_CONFIGURATION_STATE_DESTROYING;
- /* Call all remove listeners */
- CALL_REMOVE_LISTENERS(struct bt_graph_listener_port_added,
- graph->listeners.source_output_port_added);
- CALL_REMOVE_LISTENERS(struct bt_graph_listener_port_added,
- graph->listeners.filter_output_port_added);
- CALL_REMOVE_LISTENERS(struct bt_graph_listener_port_added,
- graph->listeners.filter_input_port_added);
- CALL_REMOVE_LISTENERS(struct bt_graph_listener_port_added,
- graph->listeners.sink_input_port_added);
-
if (graph->messages) {
g_ptr_array_free(graph->messages, TRUE);
graph->messages = NULL;
if (graph->messages) {
g_ptr_array_free(graph->messages, TRUE);
graph->messages = NULL;
bt_graph_add_source_component_output_port_added_listener(
struct bt_graph *graph,
bt_graph_source_component_output_port_added_listener_func func,
bt_graph_add_source_component_output_port_added_listener(
struct bt_graph *graph,
bt_graph_source_component_output_port_added_listener_func func,
- bt_graph_listener_removed_func listener_removed, void *data,
- bt_listener_id *out_listener_id)
+ void *data, bt_listener_id *out_listener_id)
{
struct bt_graph_listener_port_added listener = {
{
struct bt_graph_listener_port_added listener = {
- .base = {
- .removed = listener_removed,
- .data = data,
- },
.func = (port_added_func_t) func,
.func = (port_added_func_t) func,
};
bt_listener_id listener_id;
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(graph, "Graph");
BT_ASSERT_PRE_NON_NULL(func, "Listener");
};
bt_listener_id listener_id;
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(graph, "Graph");
BT_ASSERT_PRE_NON_NULL(func, "Listener");
- BT_ASSERT_PRE_NON_NULL(func, "\"Listener removed\" listener");
- BT_ASSERT_PRE(!graph->in_remove_listener,
- "Graph currently executing a \"listener removed\" listener: "
- "%!+g", graph);
g_array_append_val(graph->listeners.source_output_port_added, listener);
listener_id = graph->listeners.source_output_port_added->len - 1;
BT_LIB_LOGD("Added \"source component output port added\" listener to graph: "
g_array_append_val(graph->listeners.source_output_port_added, listener);
listener_id = graph->listeners.source_output_port_added->len - 1;
BT_LIB_LOGD("Added \"source component output port added\" listener to graph: "
bt_graph_add_filter_component_output_port_added_listener(
struct bt_graph *graph,
bt_graph_filter_component_output_port_added_listener_func func,
bt_graph_add_filter_component_output_port_added_listener(
struct bt_graph *graph,
bt_graph_filter_component_output_port_added_listener_func func,
- bt_graph_listener_removed_func listener_removed, void *data,
- bt_listener_id *out_listener_id)
+ void *data, bt_listener_id *out_listener_id)
{
struct bt_graph_listener_port_added listener = {
{
struct bt_graph_listener_port_added listener = {
- .base = {
- .removed = listener_removed,
- .data = data,
- },
.func = (port_added_func_t) func,
.func = (port_added_func_t) func,
};
bt_listener_id listener_id;
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(graph, "Graph");
BT_ASSERT_PRE_NON_NULL(func, "Listener");
};
bt_listener_id listener_id;
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(graph, "Graph");
BT_ASSERT_PRE_NON_NULL(func, "Listener");
- BT_ASSERT_PRE_NON_NULL(func, "\"Listener removed\" listener");
- BT_ASSERT_PRE(!graph->in_remove_listener,
- "Graph currently executing a \"listener removed\" listener: "
- "%!+g", graph);
g_array_append_val(graph->listeners.filter_output_port_added, listener);
listener_id = graph->listeners.filter_output_port_added->len - 1;
BT_LIB_LOGD("Added \"filter component output port added\" listener to graph: "
g_array_append_val(graph->listeners.filter_output_port_added, listener);
listener_id = graph->listeners.filter_output_port_added->len - 1;
BT_LIB_LOGD("Added \"filter component output port added\" listener to graph: "
bt_graph_add_filter_component_input_port_added_listener(
struct bt_graph *graph,
bt_graph_filter_component_input_port_added_listener_func func,
bt_graph_add_filter_component_input_port_added_listener(
struct bt_graph *graph,
bt_graph_filter_component_input_port_added_listener_func func,
- bt_graph_listener_removed_func listener_removed, void *data,
- bt_listener_id *out_listener_id)
+ void *data, bt_listener_id *out_listener_id)
{
struct bt_graph_listener_port_added listener = {
{
struct bt_graph_listener_port_added listener = {
- .base = {
- .removed = listener_removed,
- .data = data,
- },
.func = (port_added_func_t) func,
.func = (port_added_func_t) func,
};
bt_listener_id listener_id;
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(graph, "Graph");
BT_ASSERT_PRE_NON_NULL(func, "Listener");
};
bt_listener_id listener_id;
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(graph, "Graph");
BT_ASSERT_PRE_NON_NULL(func, "Listener");
- BT_ASSERT_PRE_NON_NULL(func, "\"Listener removed\" listener");
- BT_ASSERT_PRE(!graph->in_remove_listener,
- "Graph currently executing a \"listener removed\" listener: "
- "%!+g", graph);
g_array_append_val(graph->listeners.filter_input_port_added, listener);
listener_id = graph->listeners.filter_input_port_added->len - 1;
BT_LIB_LOGD("Added \"filter component input port added\" listener to graph: "
g_array_append_val(graph->listeners.filter_input_port_added, listener);
listener_id = graph->listeners.filter_input_port_added->len - 1;
BT_LIB_LOGD("Added \"filter component input port added\" listener to graph: "
bt_graph_add_sink_component_input_port_added_listener(
struct bt_graph *graph,
bt_graph_sink_component_input_port_added_listener_func func,
bt_graph_add_sink_component_input_port_added_listener(
struct bt_graph *graph,
bt_graph_sink_component_input_port_added_listener_func func,
- bt_graph_listener_removed_func listener_removed, void *data,
- bt_listener_id *out_listener_id)
+ void *data, bt_listener_id *out_listener_id)
{
struct bt_graph_listener_port_added listener = {
{
struct bt_graph_listener_port_added listener = {
- .base = {
- .removed = listener_removed,
- .data = data,
- },
.func = (port_added_func_t) func,
.func = (port_added_func_t) func,
};
bt_listener_id listener_id;
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(graph, "Graph");
BT_ASSERT_PRE_NON_NULL(func, "Listener");
};
bt_listener_id listener_id;
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(graph, "Graph");
BT_ASSERT_PRE_NON_NULL(func, "Listener");
- BT_ASSERT_PRE_NON_NULL(func, "\"Listener removed\" listener");
- BT_ASSERT_PRE(!graph->in_remove_listener,
- "Graph currently executing a \"listener removed\" listener: "
- "%!+g", graph);
g_array_append_val(graph->listeners.sink_input_port_added, listener);
listener_id = graph->listeners.sink_input_port_added->len - 1;
BT_LIB_LOGD("Added \"sink component input port added\" listener to graph: "
g_array_append_val(graph->listeners.sink_input_port_added, listener);
listener_id = graph->listeners.sink_input_port_added->len - 1;
BT_LIB_LOGD("Added \"sink component input port added\" listener to graph: "
BT_ASSERT(listener->func);
BT_ASSERT(listener->func);
- status = listener->func(comp, port, listener->base.data);
+ status = listener->func(comp, port, listener->data);
BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(status);
if (status != BT_FUNC_STATUS_OK) {
goto end;
BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(status);
if (status != BT_FUNC_STATUS_OK) {
goto end;
*/
struct bt_interrupter *default_interrupter;
*/
struct bt_interrupter *default_interrupter;
- bool in_remove_listener;
BT_ASSERT(graph);
ret = bt_graph_add_source_component_output_port_added_listener(
BT_ASSERT(graph);
ret = bt_graph_add_source_component_output_port_added_listener(
- graph, graph_src_output_port_added, NULL, NULL, NULL);
+ graph, graph_src_output_port_added, NULL, NULL);
BT_ASSERT(ret >= 0);
ret = bt_graph_add_sink_component_input_port_added_listener(
BT_ASSERT(ret >= 0);
ret = bt_graph_add_sink_component_input_port_added_listener(
- graph, graph_sink_input_port_added, NULL, NULL, NULL);
+ graph, graph_sink_input_port_added, NULL, NULL);
BT_ASSERT(ret >= 0);
return graph;
}
BT_ASSERT(ret >= 0);
return graph;
}