/* commons.hpp - common definitions and utils for the io_uring video output demo code 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. * ************************************************************************/ #ifndef COMMONS_H #define COMMONS_H #include <cstdint> #include <iostream> #include <chrono> #include <string> #include <array> #include <linux/time_types.h> // for struct __kernel_timespec using std::string; using uint = unsigned int; using FrameRate = uint; inline void __FAIL (string msg) { std::cerr << "FAIL: " << msg << std::endl; std::abort(); } /** * Marker class: any copy and copy construction prohibited */ class NonCopyable { protected: ~NonCopyable() = default; NonCopyable() = default; NonCopyable (NonCopyable const&) = delete; NonCopyable& operator= (NonCopyable const&) = delete; }; /** * Generate a kernel timespec from a given C++ chrono duration */ template<class REP, class SCALE> constexpr struct __kernel_timespec asKernelTimespec (std::chrono::duration<REP, SCALE> dur) { using namespace std::chrono; auto secs = duration_cast<seconds>(dur); auto nsecs = duration_cast<nanoseconds>(dur - secs); return __kernel_timespec{ static_cast<long long> (secs.count()) , static_cast<long long> (nsecs.count()) }; } /** * A series of timers for performance measurement, that can be used in interleaved. * When marking the end of each timed interval, the resulting duration is committed * into an exponential moving average of all observed timings. * @note not threadsafe, only to be used from within a single thread. */ template<uint cnt, uint ema_period> class OverlappingTimers { using Scale = std::micro; // timings in µs using Clock = std::chrono::steady_clock; using Time = decltype(Clock::now()); using Dur = std::chrono::duration<double, Scale>; std::array<Time, cnt> timer_{Time{}}; /** damping factor to compute exponential moving average EMA(i) = value(i)/N + (N-1)/N · EMA(i-1) */ static constexpr double ALPHA = 1.0 / ema_period; double expMA_{1}; public: double expMA() { return expMA_; } void markStart (uint timerID) { timer_[timerID % cnt] = Clock::now(); } double markStop (uint timerID) { Dur duration = Clock::now () - timer_[timerID % cnt]; double runTime = duration.count(); expMA_ = ALPHA * runTime + (1-ALPHA) * expMA_; return runTime; } }; #endif /*COMMONS_H*/