*/
#define BT_LOG_TAG "TRACE"
-#include <babeltrace/lib-logging-internal.h>
-
-#include <babeltrace/assert-pre-internal.h>
-#include <babeltrace/trace-ir/trace.h>
-#include <babeltrace/trace-ir/trace-class-internal.h>
-#include <babeltrace/trace-ir/trace-const.h>
-#include <babeltrace/trace-ir/trace-internal.h>
-#include <babeltrace/trace-ir/clock-class-internal.h>
-#include <babeltrace/trace-ir/stream-internal.h>
-#include <babeltrace/trace-ir/stream-class-internal.h>
-#include <babeltrace/trace-ir/event-internal.h>
-#include <babeltrace/trace-ir/event-class.h>
-#include <babeltrace/trace-ir/event-class-internal.h>
-#include <babeltrace/ctf-writer/functor-internal.h>
-#include <babeltrace/ctf-writer/clock-internal.h>
-#include <babeltrace/trace-ir/field-wrapper-internal.h>
-#include <babeltrace/trace-ir/field-class-internal.h>
-#include <babeltrace/trace-ir/attributes-internal.h>
-#include <babeltrace/trace-ir/utils-internal.h>
-#include <babeltrace/trace-ir/resolve-field-path-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/value.h>
-#include <babeltrace/value-const.h>
-#include <babeltrace/value-internal.h>
-#include <babeltrace/types.h>
-#include <babeltrace/endian-internal.h>
-#include <babeltrace/assert-internal.h>
-#include <babeltrace/compat/glib-internal.h>
+#include <babeltrace2/lib-logging-internal.h>
+
+#include <babeltrace2/assert-pre-internal.h>
+#include <babeltrace2/trace-ir/trace.h>
+#include <babeltrace2/trace-ir/trace-class-internal.h>
+#include <babeltrace2/trace-ir/trace-const.h>
+#include <babeltrace2/trace-ir/trace-internal.h>
+#include <babeltrace2/trace-ir/clock-class-internal.h>
+#include <babeltrace2/trace-ir/stream-internal.h>
+#include <babeltrace2/trace-ir/stream-class-internal.h>
+#include <babeltrace2/trace-ir/event-internal.h>
+#include <babeltrace2/trace-ir/event-class.h>
+#include <babeltrace2/trace-ir/event-class-internal.h>
+#include <babeltrace2/ctf-writer/functor-internal.h>
+#include <babeltrace2/ctf-writer/clock-internal.h>
+#include <babeltrace2/trace-ir/field-wrapper-internal.h>
+#include <babeltrace2/trace-ir/field-class-internal.h>
+#include <babeltrace2/trace-ir/attributes-internal.h>
+#include <babeltrace2/trace-ir/utils-internal.h>
+#include <babeltrace2/trace-ir/resolve-field-path-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/value.h>
+#include <babeltrace2/value-const.h>
+#include <babeltrace2/value-internal.h>
+#include <babeltrace2/types.h>
+#include <babeltrace2/endian-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compat/glib-internal.h>
#include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
-struct bt_trace_is_static_listener_elem {
- bt_trace_is_static_listener_func func;
- bt_trace_listener_removed_func removed;
+struct bt_trace_destruction_listener_elem {
+ bt_trace_destruction_listener_func func;
void *data;
};
BT_LIB_LOGD("Destroying trace object: %!+t", trace);
/*
- * Call remove listeners first so that everything else still
- * exists in the trace.
+ * Call destruction listener functions so that everything else
+ * still exists in the trace.
*/
- if (trace->is_static_listeners) {
- size_t i;
-
- for (i = 0; i < trace->is_static_listeners->len; i++) {
- struct bt_trace_is_static_listener_elem elem =
- g_array_index(trace->is_static_listeners,
- struct bt_trace_is_static_listener_elem, i);
-
- if (elem.removed) {
- elem.removed((void *) trace, elem.data);
+ if (trace->destruction_listeners) {
+ uint64_t i;
+ BT_LIB_LOGV("Calling trace destruction listener(s): %!+t", trace);
+
+ /*
+ * The trace'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 a destruction listener did
+ * bt_object_get_ref() (or anything that causes
+ * bt_object_get_ref() to be called) on the trace (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.
+ */
+ trace->base.ref_count++;
+
+ /* Call all the trace destruction listeners */
+ for (i = 0; i < trace->destruction_listeners->len; i++) {
+ struct bt_trace_destruction_listener_elem elem =
+ g_array_index(trace->destruction_listeners,
+ struct bt_trace_destruction_listener_elem, i);
+
+ if (elem.func) {
+ elem.func(trace, elem.data);
}
- }
- g_array_free(trace->is_static_listeners, TRUE);
- trace->is_static_listeners = NULL;
+ /*
+ * The destruction listener should not have kept a
+ * reference to the trace.
+ */
+ BT_ASSERT_PRE(trace->base.ref_count == 1, "Destruction listener kept a reference to the trace being destroyed: %![trace-]+t", trace);
+ }
+ g_array_free(trace->destruction_listeners, TRUE);
+ trace->destruction_listeners = NULL;
}
if (trace->name.str) {
goto error;
}
- trace->is_static_listeners = g_array_new(FALSE, TRUE,
- sizeof(struct bt_trace_is_static_listener_elem));
- if (!trace->is_static_listeners) {
+ trace->destruction_listeners = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_trace_destruction_listener_elem));
+ if (!trace->destruction_listeners) {
BT_LOGE_STR("Failed to allocate one GArray.");
goto error;
}
return bt_trace_borrow_stream_by_id((void *) trace, id);
}
-bt_bool bt_trace_is_static(const struct bt_trace *trace)
-{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return (bt_bool) trace->is_static;
-}
-
-enum bt_trace_status bt_trace_make_static(struct bt_trace *trace)
-{ uint64_t i;
-
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- trace->is_static = true;
- bt_trace_freeze(trace);
- BT_LIB_LOGV("Trace is now static: %!+t", trace);
-
- /* Call all the "trace is static" listeners */
- for (i = 0; i < trace->is_static_listeners->len; i++) {
- struct bt_trace_is_static_listener_elem elem =
- g_array_index(trace->is_static_listeners,
- struct bt_trace_is_static_listener_elem, i);
-
- if (elem.func) {
- elem.func((void *) trace, elem.data);
- }
- }
-
- return BT_TRACE_STATUS_OK;
-}
-
-enum bt_trace_status bt_trace_add_is_static_listener(
+enum bt_trace_status bt_trace_add_destruction_listener(
const struct bt_trace *c_trace,
- bt_trace_is_static_listener_func listener,
- bt_trace_listener_removed_func listener_removed, void *data,
- uint64_t *listener_id)
+ bt_trace_destruction_listener_func listener,
+ void *data, uint64_t *listener_id)
{
struct bt_trace *trace = (void *) c_trace;
uint64_t i;
- struct bt_trace_is_static_listener_elem new_elem = {
+ struct bt_trace_destruction_listener_elem new_elem = {
.func = listener,
- .removed = listener_removed,
.data = data,
};
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
BT_ASSERT_PRE_NON_NULL(listener, "Listener");
- BT_ASSERT_PRE(!trace->is_static,
- "Trace is already static: %!+t", trace);
- BT_ASSERT_PRE(trace->in_remove_listener,
- "Cannot call this function while executing a "
- "remove listener: %!+t", trace);
/* Find the next available spot */
- for (i = 0; i < trace->is_static_listeners->len; i++) {
- struct bt_trace_is_static_listener_elem elem =
- g_array_index(trace->is_static_listeners,
- struct bt_trace_is_static_listener_elem, i);
+ for (i = 0; i < trace->destruction_listeners->len; i++) {
+ struct bt_trace_destruction_listener_elem elem =
+ g_array_index(trace->destruction_listeners,
+ struct bt_trace_destruction_listener_elem, i);
if (!elem.func) {
break;
}
}
- if (i == trace->is_static_listeners->len) {
- g_array_append_val(trace->is_static_listeners, new_elem);
+ if (i == trace->destruction_listeners->len) {
+ g_array_append_val(trace->destruction_listeners, new_elem);
} else {
- g_array_insert_val(trace->is_static_listeners, i, new_elem);
+ g_array_insert_val(trace->destruction_listeners, i, new_elem);
}
if (listener_id) {
*listener_id = i;
}
- BT_LIB_LOGV("Added \"trace is static\" listener: "
- "%![trace-]+t, listener-id=%" PRIu64, trace, i);
+ BT_LIB_LOGV("Added destruction listener: " "%![trace-]+t, "
+ "listener-id=%" PRIu64, trace, i);
return BT_TRACE_STATUS_OK;
}
static
bool has_listener_id(const struct bt_trace *trace, uint64_t listener_id)
{
- BT_ASSERT(listener_id < trace->is_static_listeners->len);
- return (&g_array_index(trace->is_static_listeners,
- struct bt_trace_is_static_listener_elem,
+ BT_ASSERT(listener_id < trace->destruction_listeners->len);
+ return (&g_array_index(trace->destruction_listeners,
+ struct bt_trace_destruction_listener_elem,
listener_id))->func != NULL;
}
-enum bt_trace_status bt_trace_remove_is_static_listener(
+enum bt_trace_status bt_trace_remove_destruction_listener(
const struct bt_trace *c_trace, uint64_t listener_id)
{
struct bt_trace *trace = (void *) c_trace;
- struct bt_trace_is_static_listener_elem *elem;
+ struct bt_trace_destruction_listener_elem *elem;
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- BT_ASSERT_PRE(!trace->is_static,
- "Trace is already static: %!+t", trace);
- BT_ASSERT_PRE(trace->in_remove_listener,
- "Cannot call this function while executing a "
- "remove listener: %!+t", trace);
BT_ASSERT_PRE(has_listener_id(trace, listener_id),
- "Trace has no such \"trace is static\" listener ID: "
+ "Trace has no such trace destruction listener ID: "
"%![trace-]+t, %" PRIu64, trace, listener_id);
- elem = &g_array_index(trace->is_static_listeners,
- struct bt_trace_is_static_listener_elem,
+ elem = &g_array_index(trace->destruction_listeners,
+ struct bt_trace_destruction_listener_elem,
listener_id);
BT_ASSERT(elem->func);
- if (elem->removed) {
- /* Call remove listener */
- BT_LIB_LOGV("Calling remove listener: "
- "%![trace-]+t, listener-id=%" PRIu64,
- trace, listener_id);
- trace->in_remove_listener = true;
- elem->removed((void *) trace, elem->data);
- trace->in_remove_listener = false;
- }
-
elem->func = NULL;
- elem->removed = NULL;
elem->data = NULL;
- BT_LIB_LOGV("Removed \"trace is static\" listener: "
+ BT_LIB_LOGV("Removed \"trace destruction listener: "
"%![trace-]+t, listener-id=%" PRIu64,
trace, listener_id);
return BT_TRACE_STATUS_OK;
BT_HIDDEN
void _bt_trace_freeze(const struct bt_trace *trace)
{
- /* The packet header field class is already frozen */
BT_ASSERT(trace);
BT_LIB_LOGD("Freezing trace's class: %!+T", trace->class);
bt_trace_class_freeze(trace->class);