/* demo-uring.cpp - async file IO with io_uring Copyright (C) 2026, Hermann Vosseler This program is free software; you can redistribute it and/or modify it   under the terms of the GNU GPL version 2+ See the LICENSE file for details. * ************************************************************************/ #include "commons.hpp" #include "egl-display.hpp" #include "gtk-uring-app.hpp" #include #include #include #include using std::unique_ptr; using std::make_unique; //-----------------hard-coded-config-- const size_t RING_SIZ = 5; const uint VIDEO_WIDTH = 320; const uint VIDEO_HEIGHT = 240; //-----------------hard-coded-config-- class UringVideoPlayer : NonCopyable { using VideoDisplay = EglDisplay; using Buffer = VideoDisplay::Buffer; enum BuffState { FREE, READ, SHOW }; using AtomicBuffState = std::atomic; using BufferAlloc = unique_ptr; using BuffStateAlloc = unique_ptr; /** * Connector to the VideoDisplay for dispatching video data. * @note inherits from Glib::Dispatcher -> signal frame readiness * @remark the callback functions allow the VideoDisplay to interact * with the buffer data and state in a threadsafe manner */ class BufferDispatcher : public VideoDisplay::PixelFeed { Buffer* retrieveFrame() override; void completedFrame() override; UringVideoPlayer& player_; public: BufferDispatcher (UringVideoPlayer& player) : player_{player} { } }; size_t nextRead_{0}; size_t nextShow_{0}; BufferAlloc buffer_{}; BuffStateAlloc buffState_{}; std::atomic_bool playing_{false}; BufferDispatcher dispatchFrame_; VideoDisplay videoDisplayer_; std::thread proactorThread_; public: UringVideoPlayer (Gtk::Window& appWindow) : dispatchFrame_{*this} , videoDisplayer_{appWindow, dispatchFrame_} , proactorThread_{[this]{ playVideo(); }} { } void terminate(); private: void playVideo(); }; /** * Logic of the »Proactor Thread«: * - maintain the working buffers * - open the raw video file to retrieve data * - establish an IO_URING connection for reading * - periodic processing to fill and hand-off buffers */ void UringVideoPlayer::playVideo() { buffer_ = make_unique (RING_SIZ); buffState_ = make_unique (RING_SIZ); // initialise URing // ++ proactor-loop ++ } UringVideoPlayer::Buffer* UringVideoPlayer::BufferDispatcher::retrieveFrame() { ///////OOO threadsafe hand-over of current frame data } void UringVideoPlayer::BufferDispatcher::completedFrame() { ///////OOO mark end of buffer access } void UringVideoPlayer::terminate() { playing_.store (false, std::memory_order_release); proactorThread_.join(); videoDisplayer_.cleanUp(); } unique_ptr launchPlayer (Gtk::Window& appWindow) { appWindow.resize (VIDEO_WIDTH, VIDEO_HEIGHT); return std::make_unique (appWindow); } int main (int, const char*[]) { return GtkUringApp{"io-uring-demo"} .onClick (launchPlayer) .onClose ([](auto& player){ player.terminate();}) .run(); }