2026-07-14 19:27:27 +02:00
|
|
|
|
/*
|
|
|
|
|
|
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>
|
2026-07-15 23:53:23 +02:00
|
|
|
|
#include <chrono>
|
2026-07-14 19:27:27 +02:00
|
|
|
|
#include <string>
|
2026-07-17 23:22:33 +02:00
|
|
|
|
#include <array>
|
2026-07-14 19:27:27 +02:00
|
|
|
|
|
2026-07-15 23:53:23 +02:00
|
|
|
|
#include <linux/time_types.h> // for struct __kernel_timespec
|
|
|
|
|
|
|
2026-07-14 19:27:27 +02:00
|
|
|
|
using std::string;
|
|
|
|
|
|
using uint = unsigned int;
|
|
|
|
|
|
using FrameRate = uint;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline void
|
|
|
|
|
|
__FAIL (string msg)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cerr << "FAIL: " << msg << std::endl;
|
|
|
|
|
|
std::abort();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-15 20:40:59 +02:00
|
|
|
|
/**
|
|
|
|
|
|
* Marker class: any copy and copy construction prohibited
|
|
|
|
|
|
*/
|
|
|
|
|
|
class NonCopyable
|
|
|
|
|
|
{
|
|
|
|
|
|
protected:
|
|
|
|
|
|
~NonCopyable() = default;
|
|
|
|
|
|
NonCopyable() = default;
|
|
|
|
|
|
NonCopyable (NonCopyable const&) = delete;
|
|
|
|
|
|
NonCopyable& operator= (NonCopyable const&) = delete;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-14 19:27:27 +02:00
|
|
|
|
|
2026-07-15 23:53:23 +02:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 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())
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-17 23:22:33 +02:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 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;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-14 19:27:27 +02:00
|
|
|
|
#endif /*COMMONS_H*/
|