#include <babeltrace/lib-logging-internal.h>
#include <babeltrace/compiler-internal.h>
+#include <babeltrace/object-internal.h>
#include <babeltrace/ctf-ir/event.h>
#include <babeltrace/ctf-ir/event-internal.h>
#include <babeltrace/ctf-ir/event-class-internal.h>
struct bt_clock_class_priority_map *cc_prio_map)
{
struct bt_notification_event *notification = NULL;
+ struct bt_event *event;
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
-
- if (cc_prio_map) {
- /* Function's reference, released at the end */
- bt_get(cc_prio_map);
- } else {
- cc_prio_map = bt_clock_class_priority_map_create();
- if (!cc_prio_map) {
- BT_LOGE_STR("Cannot create empty clock class priority map.");
- goto error;
- }
- }
-
- BT_ASSERT(cc_prio_map);
+ BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map");
BT_LOGD("Creating event notification object: "
"event-class-addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64 ", "
event_class,
bt_event_class_get_name(event_class),
bt_event_class_get_id(event_class), cc_prio_map);
-
BT_ASSERT_PRE(event_class_has_trace(event_class),
"Event class is not part of a trace: %!+E", event_class);
- notification = (void *) bt_notification_create_from_pool(
- &graph->event_notif_pool, graph);
- if (!notification) {
- /* bt_notification_create_from_pool() logs errors */
+ event = bt_event_create(event_class, packet);
+ if (unlikely(!event)) {
+ BT_LIB_LOGE("Cannot create event from event class: "
+ "%![event-class-]+E", event_class);
goto error;
}
- notification->event = bt_event_create(event_class, packet);
- if (!notification->event) {
- BT_LIB_LOGE("Cannot create event from event class: "
- "%![event-class-]+E", event_class);
+ /*
+ * Create notification from pool _after_ we have everything
+ * (in this case, a valid event object) so that we never have an
+ * error condition with a non-NULL notification object.
+ * Otherwise:
+ *
+ * * We cannot recycle the notification on error because
+ * bt_notification_event_recycle() expects a complete
+ * notification (and the event or clock class priority map
+ * object could be unset).
+ *
+ * * We cannot destroy the notification because we would need
+ * to notify the graph (pool owner) so that it removes the
+ * notification from its notification array.
+ */
+ notification = (void *) bt_notification_create_from_pool(
+ &graph->event_notif_pool, graph);
+ if (unlikely(!notification)) {
+ /* bt_notification_create_from_pool() logs errors */
goto error;
}
- notification->cc_prio_map = bt_get(cc_prio_map);
+ BT_ASSERT(!notification->cc_prio_map);
+ notification->cc_prio_map = cc_prio_map;
+ bt_object_get_no_null_check_no_parent_check(
+ ¬ification->cc_prio_map->base);
+ BT_ASSERT(!notification->event);
+ notification->event = event;
BT_LOGD_STR("Freezing event notification's clock class priority map.");
bt_clock_class_priority_map_freeze(notification->cc_prio_map);
BT_LOGD("Created event notification object: "
goto end;
error:
- BT_PUT(notification);
+ BT_ASSERT(!notification);
+ bt_event_destroy(event);
end:
- bt_put(cc_prio_map);
return (void *) notification;
}
BT_ASSERT(event_notif);
- if (!notif->graph) {
+ if (unlikely(!notif->graph)) {
bt_notification_event_destroy(notif);
return;
}
BT_LOGD("Recycling event notification: addr=%p", notif);
bt_notification_reset(notif);
-
- if (event_notif->event) {
- BT_LOGD_STR("Recycling event.");
- bt_event_recycle(event_notif->event);
- event_notif->event = NULL;
- }
-
- BT_PUT(event_notif->cc_prio_map);
+ BT_ASSERT(event_notif->event);
+ BT_LOGD_STR("Recycling event.");
+ bt_event_recycle(event_notif->event);
+ event_notif->event = NULL;
+ bt_object_put_no_null_check(&event_notif->cc_prio_map->base);
+ event_notif->cc_prio_map = NULL;
graph = notif->graph;
notif->graph = NULL;
bt_object_pool_recycle_object(&graph->event_notif_pool, notif);