wegen/FrOSCon26/examples/demo-uring.cpp

145 lines
3.3 KiB
C++
Raw Normal View History

/*
demo-uring.cpp - async file IO with io_uring
Copyright (C)
2026, Hermann Vosseler <Ichthyostega@web.de>
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 <iostream>
#include <memory>
#include <thread>
#include <atomic>
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<uint8_t, VIDEO_WIDTH,VIDEO_HEIGHT>;
using Buffer = VideoDisplay::Buffer;
enum BuffState { FREE, READ, SHOW };
using AtomicBuffState = std::atomic<BuffState>;
using BufferAlloc = unique_ptr<Buffer[]>;
using BuffStateAlloc = unique_ptr<AtomicBuffState[]>;
/**
* 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<Buffer[]> (RING_SIZ);
buffState_ = make_unique<AtomicBuffState[]> (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<UringVideoPlayer>
launchPlayer (Gtk::Window& appWindow)
{
appWindow.resize (VIDEO_WIDTH, VIDEO_HEIGHT);
return std::make_unique<UringVideoPlayer> (appWindow);
}
int
main (int, const char*[])
{
return GtkUringApp<UringVideoPlayer>{"io-uring-demo"}
.onClick (launchPlayer)
.onClose ([](auto& player){ player.terminate();})
.run();
}