wegen/FrOSCon26/examples/commons.hpp

107 lines
2.8 KiB
C++
Raw Normal View History

/*
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*/