#pragma once
#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <cstdint>
#include <utility>
#define LOG(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
#define LOG_ERRNO(fmt, ...) LOG(fmt " - %d: %s", ##__VA_ARGS__, errno, strerror(errno))
#ifdef NDEBUG
#define INLINE inline __attribute__((always_inline))
#else
#define INLINE
#endif
#define PACKED __attribute__((packed))
#define UNUSED __attribute__((unused))
#if 0
#define ALIGN(b) __attribute__((aligned(b)))
#else
#define ALIGN(b) alignas(b) // should work for make_unique[]
#endif
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define MICRO_COORD (1.0e-6F)
#define MICRO_DIST (1.0e-3F)
typedef uint64_t msec_t;
/** @brief Monotonic game clock and timer with millisecond resolution. */
class Timer {
private:
msec_t start;
public:
Timer() : start{now()} {}
static msec_t now() {
struct timespec ts {};
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
return (static_cast<msec_t>(ts.tv_sec) * 1000) + (static_cast<msec_t>(ts.tv_nsec) / 1000000);
}
/** @brief restart */
void reset() {
start = now();
}
/** @brief elapsed time since start */
msec_t measure() const {
return now() - start;
}
/** @brief elapsed time and immediately restart */
msec_t measurement() {
const msec_t ts = now();
return ts - std::exchange(start, ts);
}
};