X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Ftrace-ir%2Ftrace-class.c;fp=lib%2Ftrace-ir%2Ftrace-class.c;h=3aa398fb94904744f0906925bfdbbe457c3ea76a;hb=ad5268b5815118fd5f01551b43e493214528f88d;hp=7fa6a2f515b62ed2fda8f977e1b1a6cc474afdd0;hpb=9dcfa80fb5ee14044c6778d0cb03c38591eb1f3d;p=babeltrace.git diff --git a/lib/trace-ir/trace-class.c b/lib/trace-ir/trace-class.c index 7fa6a2f5..3aa398fb 100644 --- a/lib/trace-ir/trace-class.c +++ b/lib/trace-ir/trace-class.c @@ -54,6 +54,11 @@ #include #include +struct bt_trace_class_destruction_listener_elem { + bt_trace_class_destruction_listener_func func; + void *data; +}; + #define BT_ASSERT_PRE_TRACE_CLASS_HOT(_tc) \ BT_ASSERT_PRE_HOT((_tc), "Trace class", ": %!+T", (_tc)) @@ -63,6 +68,26 @@ void destroy_trace_class(struct bt_object *obj) struct bt_trace_class *tc = (void *) obj; BT_LIB_LOGD("Destroying trace class object: %!+T", tc); + /* + * Call destruction listener functions so that everything else + * still exists in the trace class. + */ + if (tc->destruction_listeners) { + uint64_t i; + BT_LIB_LOGV("Calling trace class destruction listener(s): %!+T", tc); + /* Call all the trace class destruction listeners */ + for (i = 0; i < tc->destruction_listeners->len; i++) { + struct bt_trace_class_destruction_listener_elem elem = + g_array_index(tc->destruction_listeners, + struct bt_trace_class_destruction_listener_elem, i); + + if (elem.func) { + elem.func(tc, elem.data); + } + } + g_array_free(tc->destruction_listeners, TRUE); + tc->destruction_listeners = NULL; + } if (tc->environment) { BT_LOGD_STR("Destroying environment attributes."); @@ -118,6 +143,13 @@ struct bt_trace_class *bt_trace_class_create(bt_self_component *self_comp) goto error; } + tc->destruction_listeners = g_array_new(FALSE, TRUE, + sizeof(struct bt_trace_class_destruction_listener_elem)); + if (!tc->destruction_listeners) { + BT_LOGE_STR("Failed to allocate one GArray."); + goto error; + } + tc->assigns_automatic_stream_class_id = true; BT_LIB_LOGD("Created trace class object: %!+T", tc); goto end; @@ -163,6 +195,80 @@ void bt_trace_class_set_uuid(struct bt_trace_class *tc, bt_uuid uuid) BT_LIB_LOGV("Set trace class's UUID: %!+T", tc); } +enum bt_trace_class_status bt_trace_class_add_destruction_listener( + const struct bt_trace_class *_tc, + bt_trace_class_destruction_listener_func listener, + void *data, uint64_t *listener_id) +{ + struct bt_trace_class *tc = (void *) _tc; + uint64_t i; + struct bt_trace_class_destruction_listener_elem new_elem = { + .func = listener, + .data = data, + }; + + BT_ASSERT_PRE_NON_NULL(tc, "Trace class"); + BT_ASSERT_PRE_NON_NULL(listener, "Listener"); + + /* Find the next available spot */ + for (i = 0; i < tc->destruction_listeners->len; i++) { + struct bt_trace_class_destruction_listener_elem elem = + g_array_index(tc->destruction_listeners, + struct bt_trace_class_destruction_listener_elem, i); + + if (!elem.func) { + break; + } + } + + if (i == tc->destruction_listeners->len) { + g_array_append_val(tc->destruction_listeners, new_elem); + } else { + g_array_insert_val(tc->destruction_listeners, i, new_elem); + } + + if (listener_id) { + *listener_id = i; + } + + BT_LIB_LOGV("Added trace class destruction listener: %![tc-]+T, " + "listener-id=%" PRIu64, tc, i); + return BT_TRACE_CLASS_STATUS_OK; +} + +BT_ASSERT_PRE_FUNC +static +bool has_listener_id(const struct bt_trace_class *tc, uint64_t listener_id) +{ + BT_ASSERT(listener_id < tc->destruction_listeners->len); + return (&g_array_index(tc->destruction_listeners, + struct bt_trace_class_destruction_listener_elem, + listener_id))->func != NULL; +} + +enum bt_trace_class_status bt_trace_class_remove_destruction_listener( + const struct bt_trace_class *_tc, uint64_t listener_id) +{ + struct bt_trace_class *tc = (void *) _tc; + struct bt_trace_class_destruction_listener_elem *elem; + + BT_ASSERT_PRE_NON_NULL(tc, "Trace class"); + BT_ASSERT_PRE(has_listener_id(tc, listener_id), + "Trace class has no such trace class destruction listener ID: " + "%![tc-]+T, %" PRIu64, tc, listener_id); + elem = &g_array_index(tc->destruction_listeners, + struct bt_trace_class_destruction_listener_elem, + listener_id); + BT_ASSERT(elem->func); + + elem->func = NULL; + elem->data = NULL; + BT_LIB_LOGV("Removed trace class destruction listener: " + "%![tc-]+T, listener-id=%" PRIu64, + tc, listener_id); + return BT_TRACE_CLASS_STATUS_OK; +} + BT_ASSERT_FUNC static bool trace_has_environment_entry(const struct bt_trace_class *tc, const char *name)