X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fgraph%2Fcomponent.c;h=6494f64883128ccb3ce0d81c5e1ac7ab305ed3bc;hb=68b66a256a54d32992dfefeaad11eea88b7df234;hp=ee8e94530063faea67dafd99772b995bf155e89a;hpb=36712f1d9ad9269638e493ca36a50979fe4da989;p=babeltrace.git diff --git a/lib/graph/component.c b/lib/graph/component.c index ee8e9453..6494f648 100644 --- a/lib/graph/component.c +++ b/lib/graph/component.c @@ -1,12 +1,7 @@ /* - * component.c - * - * Babeltrace Plugin Component - * + * Copyright 2017-2018 Philippe Proulx * Copyright 2015 Jérémie Galarneau * - * Author: Jérémie Galarneau - * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -27,32 +22,35 @@ */ #define BT_LOG_TAG "COMP" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include static struct bt_component * (* const component_create_funcs[])( - struct bt_component_class *) = { + const struct bt_component_class *) = { [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_create, [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_create, [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_create, @@ -66,10 +64,51 @@ void (*component_destroy_funcs[])(struct bt_component *) = { }; static -void bt_component_destroy(struct bt_object *obj) +void finalize_component(struct bt_component *comp) +{ + typedef void (*method_t)(void *); + + method_t method = NULL; + + BT_ASSERT(comp); + + switch (comp->class->type) { + case BT_COMPONENT_CLASS_TYPE_SOURCE: + { + struct bt_component_class_source *src_cc = (void *) comp->class; + + method = (method_t) src_cc->methods.finalize; + break; + } + case BT_COMPONENT_CLASS_TYPE_FILTER: + { + struct bt_component_class_filter *flt_cc = (void *) comp->class; + + method = (method_t) flt_cc->methods.finalize; + break; + } + case BT_COMPONENT_CLASS_TYPE_SINK: + { + struct bt_component_class_sink *sink_cc = (void *) comp->class; + + method = (method_t) sink_cc->methods.finalize; + break; + } + default: + abort(); + } + + if (method) { + BT_LIB_LOGD("Calling user's finalization method: " + "%![comp-]+c", comp); + method(comp); + } +} + +static +void destroy_component(struct bt_object *obj) { struct bt_component *component = NULL; - struct bt_component_class *component_class = NULL; int i; if (!obj) { @@ -80,16 +119,16 @@ void bt_component_destroy(struct bt_object *obj) * The component's reference count is 0 if we're here. Increment * it to avoid a double-destroy (possibly infinitely recursive). * This could happen for example if the component's finalization - * function does bt_get() (or anything that causes bt_get() to - * be called) on itself (ref. count goes from 0 to 1), and then - * bt_put(): the reference count would go from 1 to 0 again and - * this function would be called again. + * function does bt_object_get_ref() (or anything that causes + * bt_object_get_ref() to be called) on itself (ref. count goes + * from 0 to 1), and then bt_object_put_ref(): the reference + * count would go from 1 to 0 again and this function would be + * called again. */ - obj->ref_count.count++; + obj->ref_count++; component = container_of(obj, struct bt_component, base); - BT_LOGD("Destroying component: addr=%p, name=\"%s\", graph-addr=%p", - component, bt_component_get_name(component), - obj->parent); + BT_LIB_LOGD("Destroying component: %![comp-]+c, %![graph-]+g", + component, bt_component_borrow_graph(component)); /* Call destroy listeners in reverse registration order */ BT_LOGD_STR("Calling destroy listeners."); @@ -102,17 +141,13 @@ void bt_component_destroy(struct bt_object *obj) listener->func(component, listener->data); } - component_class = component->class; - /* * User data is destroyed first, followed by the concrete * component instance. Do not finalize if the component's user * initialization method failed in the first place. */ - if (component->initialized && component->class->methods.finalize) { - BT_LOGD_STR("Calling user's finalization method."); - component->class->methods.finalize( - bt_private_component_from_component(component)); + if (component->initialized) { + finalize_component(component); } if (component->destroy) { @@ -123,82 +158,70 @@ void bt_component_destroy(struct bt_object *obj) if (component->input_ports) { BT_LOGD_STR("Destroying input ports."); g_ptr_array_free(component->input_ports, TRUE); + component->input_ports = NULL; } if (component->output_ports) { BT_LOGD_STR("Destroying output ports."); g_ptr_array_free(component->output_ports, TRUE); + component->output_ports = NULL; } if (component->destroy_listeners) { g_array_free(component->destroy_listeners, TRUE); + component->destroy_listeners = NULL; } if (component->name) { g_string_free(component->name, TRUE); + component->name = NULL; } - BT_LOGD("Putting component class."); - bt_put(component_class); + BT_LOGD_STR("Putting component class."); + BT_OBJECT_PUT_REF_AND_RESET(component->class); g_free(component); } -struct bt_component *bt_component_from_private_component( - struct bt_private_component *private_component) -{ - return bt_get(bt_component_from_private(private_component)); -} - enum bt_component_class_type bt_component_get_class_type( - struct bt_component *component) + const struct bt_component *component) { - return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN; + BT_ASSERT_PRE_NON_NULL(component, "Component"); + return component->class->type; } static -struct bt_port *bt_component_add_port( +enum bt_self_component_status add_port( struct bt_component *component, GPtrArray *ports, - enum bt_port_type port_type, const char *name, void *user_data) + enum bt_port_type port_type, const char *name, void *user_data, + struct bt_port **port) { - size_t i; struct bt_port *new_port = NULL; struct bt_graph *graph = NULL; - - if (!name) { - BT_LOGW_STR("Invalid parameter: name is NULL."); - goto end; - } - - if (strlen(name) == 0) { - BT_LOGW_STR("Invalid parameter: name is an empty string."); - goto end; - } - - BT_LOGD("Adding port to component: comp-addr=%p, comp-name=\"%s\", " + enum bt_self_component_status status; + + BT_ASSERT_PRE_NON_NULL(component, "Component"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE(strlen(name) > 0, "Name is empty"); + graph = bt_component_borrow_graph(component); + BT_ASSERT_PRE(graph && !bt_graph_is_canceled(graph), + "Component's graph is canceled: %![comp-]+c, %![graph-]+g", + component, graph); + BT_ASSERT_PRE( + graph->config_state == BT_GRAPH_CONFIGURATION_STATE_CONFIGURING, + "Component's graph is already configured: " + "%![comp-]+c, %![graph-]+g", component, graph); + + // TODO: Validate that the name is not already used. + + BT_LIB_LOGD("Adding port to component: %![comp-]+c, " "port-type=%s, port-name=\"%s\"", component, - bt_component_get_name(component), bt_port_type_string(port_type), name); - /* Look for a port having the same name. */ - for (i = 0; i < ports->len; i++) { - const char *port_name; - struct bt_port *port = g_ptr_array_index(ports, i); - - port_name = bt_port_get_name(port); - assert(port_name); - - if (!strcmp(name, port_name)) { - /* Port name clash, abort. */ - BT_LOGW("Invalid parameter: another port with the same name already exists in the component: " - "other-port-addr=%p", port); - goto end; - } - } - new_port = bt_port_create(component, port_type, name, user_data); if (!new_port) { - BT_LOGE("Cannot create port object."); - goto end; + BT_LOGE_STR("Cannot create port object."); + status = BT_SELF_COMPONENT_STATUS_NOMEM; + goto error; } /* @@ -212,81 +235,95 @@ struct bt_port *bt_component_add_port( /* * Notify the graph's creator that a new port was added. */ - graph = bt_component_get_graph(component); + graph = bt_component_borrow_graph(component); if (graph) { - bt_graph_notify_port_added(graph, new_port); - BT_PUT(graph); + enum bt_graph_listener_status listener_status; + + listener_status = bt_graph_notify_port_added(graph, new_port); + if (listener_status != BT_GRAPH_LISTENER_STATUS_OK) { + bt_graph_make_faulty(graph); + status = listener_status; + goto error; + } } - BT_LOGD("Created and added port to component: comp-addr=%p, comp-name=\"%s\", " - "port-type=%s, port-name=\"%s\", port-addr=%p", component, - bt_component_get_name(component), - bt_port_type_string(port_type), name, new_port); + BT_LIB_LOGD("Created and added port to component: " + "%![comp-]+c, %![port-]+p", component, new_port); + + *port = new_port; + status = BT_SELF_COMPONENT_STATUS_OK; + + goto end; +error: + /* + * We need to release the reference that we would otherwise have + * returned to the caller. + */ + BT_PORT_PUT_REF_AND_RESET(new_port); end: - return new_port; + return status; } BT_HIDDEN -int64_t bt_component_get_input_port_count(struct bt_component *comp) +uint64_t bt_component_get_input_port_count(const struct bt_component *comp) { - assert(comp); - return (int64_t) comp->input_ports->len; + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + return (uint64_t) comp->input_ports->len; } BT_HIDDEN -int64_t bt_component_get_output_port_count(struct bt_component *comp) +uint64_t bt_component_get_output_port_count(const struct bt_component *comp) { - assert(comp); - return (int64_t) comp->output_ports->len; + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + return (uint64_t) comp->output_ports->len; } -enum bt_component_status bt_component_create( - struct bt_component_class *component_class, +BT_HIDDEN +int bt_component_create(struct bt_component_class *component_class, const char *name, struct bt_component **user_component) { - enum bt_component_status status = BT_COMPONENT_STATUS_OK; + int ret = 0; struct bt_component *component = NULL; enum bt_component_class_type type; - assert(user_component); - assert(component_class); - assert(name); - + BT_ASSERT(user_component); + BT_ASSERT(component_class); + BT_ASSERT(name); type = bt_component_class_get_type(component_class); - BT_LOGD("Creating empty component from component class: " - "comp-cls-addr=%p, comp-cls-type=%s, name=\"%s\"", - component_class, bt_component_class_type_string(type), name); + BT_LIB_LOGD("Creating empty component from component class: %![cc-]+C, " + "comp-name=\"%s\"", component_class, name); component = component_create_funcs[type](component_class); if (!component) { BT_LOGE_STR("Cannot create specific component object."); - status = BT_COMPONENT_STATUS_NOMEM; + ret = -1; goto end; } - bt_object_init(component, bt_component_destroy); - component->class = bt_get(component_class); + bt_object_init_shared_with_parent(&component->base, destroy_component); + component->class = component_class; + bt_object_get_no_null_check(component->class); component->destroy = component_destroy_funcs[type]; component->name = g_string_new(name); if (!component->name) { BT_LOGE_STR("Failed to allocate one GString."); - status = BT_COMPONENT_STATUS_NOMEM; + ret = -1; goto end; } component->input_ports = g_ptr_array_new_with_free_func( - bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!component->input_ports) { BT_LOGE_STR("Failed to allocate one GPtrArray."); - status = BT_COMPONENT_STATUS_NOMEM; + ret = -1; goto end; } component->output_ports = g_ptr_array_new_with_free_func( - bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!component->output_ports) { BT_LOGE_STR("Failed to allocate one GPtrArray."); - status = BT_COMPONENT_STATUS_NOMEM; + ret = -1; goto end; } @@ -294,106 +331,78 @@ enum bt_component_status bt_component_create( sizeof(struct bt_component_destroy_listener)); if (!component->destroy_listeners) { BT_LOGE_STR("Failed to allocate one GArray."); - status = BT_COMPONENT_STATUS_NOMEM; + ret = -1; goto end; } - BT_LOGD("Created empty component from component class: " - "comp-cls-addr=%p, comp-cls-type=%s, name=\"%s\", comp-addr=%p", - component_class, bt_component_class_type_string(type), name, - component); - BT_MOVE(*user_component, component); + BT_LIB_LOGD("Created empty component from component class: " + "%![cc-]+C, %![comp-]+c", component_class, component); + BT_OBJECT_MOVE_REF(*user_component, component); end: - bt_put(component); - return status; + bt_object_put_ref(component); + return ret; } -const char *bt_component_get_name(struct bt_component *component) +const char *bt_component_get_name(const struct bt_component *component) { - const char *ret = NULL; - - if (!component) { - BT_LOGW_STR("Invalid parameter: component is NULL."); - goto end; - } - - ret = component->name->len == 0 ? NULL : component->name->str; - -end: - return ret; + BT_ASSERT_PRE_NON_NULL(component, "Component"); + return component->name->str; } -struct bt_component_class *bt_component_get_class( - struct bt_component *component) +const struct bt_component_class *bt_component_borrow_class_const( + const struct bt_component *component) { - return component ? bt_get(component->class) : NULL; + BT_ASSERT_PRE_NON_NULL(component, "Component"); + return component->class; } -void *bt_private_component_get_user_data( - struct bt_private_component *private_component) +void *bt_self_component_get_data(const struct bt_self_component *self_comp) { - struct bt_component *component = - bt_component_from_private(private_component); + struct bt_component *component = (void *) self_comp; - return component ? component->user_data : NULL; + BT_ASSERT_PRE_NON_NULL(component, "Component"); + return component->user_data; } -enum bt_component_status bt_private_component_set_user_data( - struct bt_private_component *private_component, +void bt_self_component_set_data(struct bt_self_component *self_comp, void *data) { - struct bt_component *component = - bt_component_from_private(private_component); - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - - if (!component) { - BT_LOGW_STR("Invalid parameter: component is NULL."); - ret = BT_COMPONENT_STATUS_INVALID; - goto end; - } + struct bt_component *component = (void *) self_comp; + BT_ASSERT_PRE_NON_NULL(component, "Component"); component->user_data = data; - BT_LOGV("Set component's user data: " - "comp-addr=%p, comp-name=\"%s\", user-data-addr=%p", - component, bt_component_get_name(component), data); - -end: - return ret; + BT_LIB_LOGV("Set component's user data: %!+c", component); } BT_HIDDEN void bt_component_set_graph(struct bt_component *component, struct bt_graph *graph) { - bt_object_set_parent(component, graph ? &graph->base : NULL); + bt_object_set_parent(&component->base, + graph ? &graph->base : NULL); } -struct bt_graph *bt_component_get_graph( - struct bt_component *component) +bt_bool bt_component_graph_is_canceled(const struct bt_component *component) { - return (struct bt_graph *) bt_object_get_parent(&component->base); + return bt_graph_is_canceled( + (void *) bt_object_borrow_parent(&component->base)); } static -struct bt_port *bt_component_get_port_by_name(GPtrArray *ports, +struct bt_port *borrow_port_by_name(GPtrArray *ports, const char *name) { - size_t i; + uint64_t i; struct bt_port *ret_port = NULL; - assert(name); + BT_ASSERT(name); for (i = 0; i < ports->len; i++) { struct bt_port *port = g_ptr_array_index(ports, i); - const char *port_name = bt_port_get_name(port); - - if (!port_name) { - continue; - } - if (!strcmp(name, port_name)) { - ret_port = bt_get(port); + if (!strcmp(name, port->name->str)) { + ret_port = port; break; } } @@ -402,240 +411,226 @@ struct bt_port *bt_component_get_port_by_name(GPtrArray *ports, } BT_HIDDEN -struct bt_port *bt_component_get_input_port_by_name(struct bt_component *comp, - const char *name) +struct bt_port_input *bt_component_borrow_input_port_by_name( + struct bt_component *comp, const char *name) { - assert(comp); - - return bt_component_get_port_by_name(comp->input_ports, name); + BT_ASSERT(comp); + return (void *) borrow_port_by_name(comp->input_ports, name); } BT_HIDDEN -struct bt_port *bt_component_get_output_port_by_name(struct bt_component *comp, - const char *name) +struct bt_port_output *bt_component_borrow_output_port_by_name( + struct bt_component *comp, const char *name) { - assert(comp); - - return bt_component_get_port_by_name(comp->output_ports, name); + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + return (void *) + borrow_port_by_name(comp->output_ports, name); } static -struct bt_port *bt_component_get_port_by_index(GPtrArray *ports, uint64_t index) +struct bt_port *borrow_port_by_index(GPtrArray *ports, uint64_t index) { - struct bt_port *port = NULL; - - if (index >= ports->len) { - BT_LOGW("Invalid parameter: index is out of bounds: " - "index=%" PRIu64 ", count=%u", - index, ports->len); - goto end; - } - - port = bt_get(g_ptr_array_index(ports, index)); -end: - return port; + BT_ASSERT(index < ports->len); + return g_ptr_array_index(ports, index); } BT_HIDDEN -struct bt_port *bt_component_get_input_port_by_index(struct bt_component *comp, - uint64_t index) +struct bt_port_input *bt_component_borrow_input_port_by_index( + struct bt_component *comp, uint64_t index) { - assert(comp); - - return bt_component_get_port_by_index(comp->input_ports, index); + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + BT_ASSERT_PRE_VALID_INDEX(index, comp->input_ports->len); + return (void *) + borrow_port_by_index(comp->input_ports, index); } BT_HIDDEN -struct bt_port *bt_component_get_output_port_by_index(struct bt_component *comp, - uint64_t index) +struct bt_port_output *bt_component_borrow_output_port_by_index( + struct bt_component *comp, uint64_t index) { - assert(comp); - - return bt_component_get_port_by_index(comp->output_ports, index); + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + BT_ASSERT_PRE_VALID_INDEX(index, comp->output_ports->len); + return (void *) + borrow_port_by_index(comp->output_ports, index); } BT_HIDDEN -struct bt_port *bt_component_add_input_port( +enum bt_self_component_status bt_component_add_input_port( struct bt_component *component, const char *name, - void *user_data) + void *user_data, struct bt_port **port) { - /* bt_component_add_port() logs details */ - return bt_component_add_port(component, component->input_ports, - BT_PORT_TYPE_INPUT, name, user_data); + /* add_port() logs details */ + return add_port(component, component->input_ports, + BT_PORT_TYPE_INPUT, name, user_data, port); } BT_HIDDEN -struct bt_port *bt_component_add_output_port( +enum bt_self_component_status bt_component_add_output_port( struct bt_component *component, const char *name, - void *user_data) + void *user_data, struct bt_port **port) { - /* bt_component_add_port() logs details */ - return bt_component_add_port(component, component->output_ports, - BT_PORT_TYPE_OUTPUT, name, user_data); + /* add_port() logs details */ + return add_port(component, component->output_ports, + BT_PORT_TYPE_OUTPUT, name, user_data, port); } -static -void bt_component_remove_port_by_index(struct bt_component *component, - GPtrArray *ports, size_t index) +BT_HIDDEN +enum bt_self_component_status bt_component_accept_port_connection( + struct bt_component *comp, struct bt_port *self_port, + struct bt_port *other_port) { - struct bt_port *port; - struct bt_graph *graph; - - assert(ports); - assert(index < ports->len); - port = g_ptr_array_index(ports, index); + typedef enum bt_self_component_status (*method_t)( + void *, void *, const void *); - BT_LOGD("Removing port from component: " - "comp-addr=%p, comp-name=\"%s\", " - "port-addr=%p, port-name=\"%s\"", - component, bt_component_get_name(component), - port, bt_port_get_name(port)); + enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK; + method_t method = NULL; - /* Disconnect both ports of this port's connection, if any */ - if (port->connection) { - bt_connection_end(port->connection, true); - } + BT_ASSERT(comp); + BT_ASSERT(self_port); + BT_ASSERT(other_port); - /* Remove from parent's array of ports (weak refs) */ - g_ptr_array_remove_index(ports, index); + switch (comp->class->type) { + case BT_COMPONENT_CLASS_TYPE_SOURCE: + { + struct bt_component_class_source *src_cc = (void *) comp->class; - /* Detach port from its component parent */ - BT_PUT(port->base.parent); + switch (self_port->type) { + case BT_PORT_TYPE_OUTPUT: + method = (method_t) src_cc->methods.accept_output_port_connection; + break; + default: + abort(); + } - /* - * Notify the graph's creator that a port is removed. - */ - graph = bt_component_get_graph(component); - if (graph) { - bt_graph_notify_port_removed(graph, component, port); - BT_PUT(graph); + break; } + case BT_COMPONENT_CLASS_TYPE_FILTER: + { + struct bt_component_class_filter *flt_cc = (void *) comp->class; - BT_LOGD("Removed port from component: " - "comp-addr=%p, comp-name=\"%s\", " - "port-addr=%p, port-name=\"%s\"", - component, bt_component_get_name(component), - port, bt_port_get_name(port)); -} - -BT_HIDDEN -enum bt_component_status bt_component_remove_port( - struct bt_component *component, struct bt_port *port) -{ - size_t i; - enum bt_component_status status = BT_COMPONENT_STATUS_OK; - GPtrArray *ports = NULL; + switch (self_port->type) { + case BT_PORT_TYPE_INPUT: + method = (method_t) flt_cc->methods.accept_input_port_connection; + break; + case BT_PORT_TYPE_OUTPUT: + method = (method_t) flt_cc->methods.accept_output_port_connection; + break; + default: + abort(); + } - if (!component) { - BT_LOGW_STR("Invalid parameter: component is NULL."); - status = BT_COMPONENT_STATUS_INVALID; - goto end; + break; } + case BT_COMPONENT_CLASS_TYPE_SINK: + { + struct bt_component_class_sink *sink_cc = (void *) comp->class; - if (!port) { - BT_LOGW_STR("Invalid parameter: port is NULL."); - status = BT_COMPONENT_STATUS_INVALID; - goto end; - } + switch (self_port->type) { + case BT_PORT_TYPE_INPUT: + method = (method_t) sink_cc->methods.accept_input_port_connection; + break; + default: + abort(); + } - if (bt_port_get_type(port) == BT_PORT_TYPE_INPUT) { - ports = component->input_ports; - } else if (bt_port_get_type(port) == BT_PORT_TYPE_OUTPUT) { - ports = component->output_ports; + break; } - - assert(ports); - - for (i = 0; i < ports->len; i++) { - struct bt_port *cur_port = g_ptr_array_index(ports, i); - - if (cur_port == port) { - bt_component_remove_port_by_index(component, - ports, i); - goto end; - } + default: + abort(); } - status = BT_COMPONENT_STATUS_NOT_FOUND; - BT_LOGW("Port to remove from component was not found: " - "comp-addr=%p, comp-name=\"%s\", " - "port-addr=%p, port-name=\"%s\"", - component, bt_component_get_name(component), - port, bt_port_get_name(port)); + if (method) { + BT_LIB_LOGD("Calling user's \"accept port connection\" method: " + "%![comp-]+c, %![self-port-]+p, %![other-port-]+p", + comp, self_port, other_port); + status = method(comp, self_port, (void *) other_port); + BT_LOGD("User method returned: status=%s", + bt_self_component_status_string(status)); + } -end: return status; } BT_HIDDEN -enum bt_component_status bt_component_accept_port_connection( +enum bt_self_component_status bt_component_port_connected( struct bt_component *comp, struct bt_port *self_port, struct bt_port *other_port) { - enum bt_component_status status = BT_COMPONENT_STATUS_OK; - - assert(comp); - assert(self_port); - assert(other_port); - - if (comp->class->methods.accept_port_connection) { - BT_LOGD("Calling user's \"accept port connection\" method: " - "comp-addr=%p, comp-name=\"%s\", " - "self-port-addr=%p, self-port-name=\"%s\", " - "other-port-addr=%p, other-port-name=\"%s\"", - comp, bt_component_get_name(comp), - self_port, bt_port_get_name(self_port), - other_port, bt_port_get_name(other_port)); - status = comp->class->methods.accept_port_connection( - bt_private_component_from_component(comp), - bt_private_port_from_port(self_port), - other_port); - BT_LOGD("User method returned: status=%s", - bt_component_status_string(status)); + typedef enum bt_self_component_status (*method_t)( + void *, void *, const void *); + + enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK; + method_t method = NULL; + + BT_ASSERT(comp); + BT_ASSERT(self_port); + BT_ASSERT(other_port); + + switch (comp->class->type) { + case BT_COMPONENT_CLASS_TYPE_SOURCE: + { + struct bt_component_class_source *src_cc = (void *) comp->class; + + switch (self_port->type) { + case BT_PORT_TYPE_OUTPUT: + method = (method_t) src_cc->methods.output_port_connected; + break; + default: + abort(); + } + + break; } + case BT_COMPONENT_CLASS_TYPE_FILTER: + { + struct bt_component_class_filter *flt_cc = (void *) comp->class; - return status; -} + switch (self_port->type) { + case BT_PORT_TYPE_INPUT: + method = (method_t) flt_cc->methods.input_port_connected; + break; + case BT_PORT_TYPE_OUTPUT: + method = (method_t) flt_cc->methods.output_port_connected; + break; + default: + abort(); + } -BT_HIDDEN -void bt_component_port_connected(struct bt_component *comp, - struct bt_port *self_port, struct bt_port *other_port) -{ - assert(comp); - assert(self_port); - assert(other_port); - - if (comp->class->methods.port_connected) { - BT_LOGD("Calling user's \"port connected\" method: " - "comp-addr=%p, comp-name=\"%s\", " - "self-port-addr=%p, self-port-name=\"%s\", " - "other-port-addr=%p, other-port-name=\"%s\"", - comp, bt_component_get_name(comp), - self_port, bt_port_get_name(self_port), - other_port, bt_port_get_name(other_port)); - comp->class->methods.port_connected( - bt_private_component_from_component(comp), - bt_private_port_from_port(self_port), other_port); + break; } -} + case BT_COMPONENT_CLASS_TYPE_SINK: + { + struct bt_component_class_sink *sink_cc = (void *) comp->class; -BT_HIDDEN -void bt_component_port_disconnected(struct bt_component *comp, - struct bt_port *port) -{ - assert(comp); - assert(port); - - if (comp->class->methods.port_disconnected) { - BT_LOGD("Calling user's \"port disconnected\" method: " - "comp-addr=%p, comp-name=\"%s\", " - "port-addr=%p, port-name=\"%s\"", - comp, bt_component_get_name(comp), - port, bt_port_get_name(port)); - comp->class->methods.port_disconnected( - bt_private_component_from_component(comp), - bt_private_port_from_port(port)); + switch (self_port->type) { + case BT_PORT_TYPE_INPUT: + method = (method_t) sink_cc->methods.input_port_connected; + break; + default: + abort(); + } + + break; + } + default: + abort(); + } + + if (method) { + BT_LIB_LOGD("Calling user's \"port connected\" method: " + "%![comp-]+c, %![self-port-]+p, %![other-port-]+p", + comp, self_port, other_port); + status = method(comp, self_port, (void *) other_port); + BT_LOGD("User method returned: status=%s", + bt_self_component_status_string(status)); + BT_ASSERT_PRE(status == BT_SELF_COMPONENT_STATUS_OK || + status == BT_SELF_COMPONENT_STATUS_ERROR || + status == BT_SELF_COMPONENT_STATUS_NOMEM, + "Unexpected returned component status: status=%s", + bt_self_component_status_string(status)); } + + return status; } BT_HIDDEN @@ -644,26 +639,24 @@ void bt_component_add_destroy_listener(struct bt_component *component, { struct bt_component_destroy_listener listener; - assert(component); - assert(func); + BT_ASSERT(component); + BT_ASSERT(func); listener.func = func; listener.data = data; g_array_append_val(component->destroy_listeners, listener); - BT_LOGV("Added destroy listener: " - "comp-addr=%p, comp-name=\"%s\", " + BT_LIB_LOGV("Added destroy listener: %![comp-]+c, " "func-addr=%p, data-addr=%p", - component, bt_component_get_name(component), - func, data); + component, func, data); } BT_HIDDEN void bt_component_remove_destroy_listener(struct bt_component *component, bt_component_destroy_listener_func func, void *data) { - size_t i; + uint64_t i; - assert(component); - assert(func); + BT_ASSERT(component); + BT_ASSERT(func); for (i = 0; i < component->destroy_listeners->len; i++) { struct bt_component_destroy_listener *listener = @@ -673,11 +666,19 @@ void bt_component_remove_destroy_listener(struct bt_component *component, if (listener->func == func && listener->data == data) { g_array_remove_index(component->destroy_listeners, i); i--; - BT_LOGV("Removed destroy listener: " - "comp-addr=%p, comp-name=\"%s\", " + BT_LIB_LOGV("Removed destroy listener: %![comp-]+c, " "func-addr=%p, data-addr=%p", - component, bt_component_get_name(component), - func, data); + component, func, data); } } } + +void bt_component_get_ref(const struct bt_component *component) +{ + bt_object_get_ref(component); +} + +void bt_component_put_ref(const struct bt_component *component) +{ + bt_object_put_ref(component); +}