// Copyright 2023, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file * @brief Helper to implement @ref xrt_session. * @author Jakob Bornecrantz * @ingroup aux_util */ #include "util/u_system.h" #include "util/u_session.h" /* * * Helpers. * */ static inline struct u_session * u_session(struct xrt_session *xs) { return (struct u_session *)xs; } /* * * Member functions. * */ static xrt_result_t push_event(struct xrt_session_event_sink *xses, const union xrt_session_event *xse) { struct u_session *us = container_of(xses, struct u_session, sink); u_session_event_push(us, xse); return XRT_SUCCESS; } static xrt_result_t poll_events(struct xrt_session *xs, union xrt_session_event *out_xse) { struct u_session *us = u_session(xs); u_session_event_pop(us, out_xse); return XRT_SUCCESS; } static void destroy(struct xrt_session *xs) { struct u_session *us = u_session(xs); struct u_session_event *event = us->events.ptr; while (event) { struct u_session_event *tmp = event->next; free(event); event = tmp; } us->events.ptr = NULL; if (us->usys != NULL) { u_system_remove_session(us->usys, &us->base, &us->sink); } free(xs); } /* * * 'Exported' functions. * */ struct u_session * u_session_create(struct u_system *usys) { struct u_session *us = U_TYPED_CALLOC(struct u_session); // xrt_session fields. us->base.poll_events = poll_events; us->base.destroy = destroy; // xrt_session_event_sink fields. us->sink.push_event = push_event; // u_session fields. XRT_MAYBE_UNUSED int ret = os_mutex_init(&us->events.mutex); assert(ret == 0); us->usys = usys; // If we got a u_system. if (usys != NULL) { u_system_add_session(usys, &us->base, &us->sink); } return us; } void u_session_event_push(struct u_session *us, const union xrt_session_event *xse) { struct u_session_event *use = U_TYPED_CALLOC(struct u_session_event); use->xse = *xse; os_mutex_lock(&us->events.mutex); // Find the last slot. struct u_session_event **slot = &us->events.ptr; while (*slot != NULL) { slot = &(*slot)->next; } *slot = use; os_mutex_unlock(&us->events.mutex); } void u_session_event_pop(struct u_session *us, union xrt_session_event *out_xse) { U_ZERO(out_xse); out_xse->type = XRT_SESSION_EVENT_NONE; os_mutex_lock(&us->events.mutex); if (us->events.ptr != NULL) { struct u_session_event *use = us->events.ptr; *out_xse = use->xse; us->events.ptr = use->next; free(use); } os_mutex_unlock(&us->events.mutex); }