openMSX
EmuDuration.hh
Go to the documentation of this file.
1#ifndef EMUDURATION_HH
2#define EMUDURATION_HH
3
4#include "narrow.hh"
5#include "serialize.hh"
6#include <cassert>
7#include <concepts>
8#include <cstdint>
9#include <limits>
10#include <type_traits>
11
12namespace openmsx {
13
14// constants
15inline constexpr uint64_t MAIN_FREQ = 3579545ULL * 960;
16inline constexpr unsigned MAIN_FREQ32 = MAIN_FREQ;
17static_assert(MAIN_FREQ < (1ull << 32), "must fit in 32 bit");
18
19
21{
22public:
23 // This is only a very small class (one 64-bit member). On 64-bit CPUs
24 // it's cheaper to pass this by value. On 32-bit CPUs pass-by-reference
25 // is cheaper.
26#ifdef __x86_64
27 using param = EmuDuration;
28#else
29 using param = const EmuDuration&;
30#endif
31
32 // friends
33 friend class EmuTime;
34
35 // constructors
36 constexpr EmuDuration() = default;
37 constexpr explicit EmuDuration(uint64_t n) : time(n) {}
38 constexpr explicit EmuDuration(double duration)
39 : time(uint64_t(duration * MAIN_FREQ + 0.5)) {}
40
41 static constexpr EmuDuration sec(unsigned x)
42 { return EmuDuration(x * MAIN_FREQ); }
43 static constexpr EmuDuration msec(unsigned x)
44 { return EmuDuration(x * MAIN_FREQ / 1000); }
45 static constexpr EmuDuration usec(unsigned x)
46 { return EmuDuration(x * MAIN_FREQ / 1000000); }
47 static constexpr EmuDuration hz(unsigned x)
48 { return EmuDuration(MAIN_FREQ / x); }
49
50 // conversions
51 [[nodiscard]] constexpr double toDouble() const { return double(time) / MAIN_FREQ32; }
52 [[nodiscard]] constexpr uint64_t length() const { return time; }
53
54 // comparison operators
55 [[nodiscard]] constexpr auto operator<=>(const EmuDuration&) const = default;
56
57 // arithmetic operators
58 [[nodiscard]] constexpr EmuDuration operator%(EmuDuration::param d) const
59 { return EmuDuration(time % d.time); }
60 [[nodiscard]] constexpr EmuDuration operator+(EmuDuration::param d) const
61 { return EmuDuration(time + d.time); }
62 [[nodiscard]] constexpr EmuDuration operator*(uint64_t fact) const
63 { return EmuDuration(time * fact); }
64 [[nodiscard]] constexpr EmuDuration operator/(unsigned fact) const
65 { return EmuDuration(time / fact); }
66 [[nodiscard]] constexpr EmuDuration divRoundUp(unsigned fact) const
67 { return EmuDuration((time + fact - 1) / fact); }
68 [[nodiscard]] constexpr unsigned operator/(EmuDuration::param d) const
69 {
70 uint64_t result = time / d.time;
71#ifdef DEBUG
72 // we don't even want this overhead in devel builds
73 assert(result == unsigned(result));
74#endif
75 return unsigned(result);
76 }
77 [[nodiscard]] constexpr unsigned divUp(EmuDuration::param d) const {
78 uint64_t result = (time + d.time - 1) / d.time;
79#ifdef DEBUG
80 assert(result == unsigned(result));
81#endif
82 return unsigned(result);
83 }
84 [[nodiscard]] constexpr double div(EmuDuration::param d) const
85 { return narrow_cast<double>(time) / narrow_cast<double>(d.time); }
86
87 constexpr EmuDuration& operator*=(unsigned fact)
88 { time *= fact; return *this; }
89 constexpr EmuDuration& operator*=(double fact)
90 { time = narrow_cast<uint64_t>(narrow_cast<double>(time) * fact); return *this; }
91 constexpr EmuDuration& operator/=(double fact)
92 { time = narrow_cast<uint64_t>(narrow_cast<double>(time) / fact); return *this; }
93
94 // ticks
95 // TODO: Used in WavAudioInput. Keep or use DynamicClock instead?
96 [[nodiscard]] constexpr unsigned getTicksAt(unsigned freq) const
97 {
98 uint64_t result = time / (MAIN_FREQ32 / freq);
99#ifdef DEBUG
100 // we don't even want this overhead in devel builds
101 assert(result == unsigned(result));
102#endif
103 return unsigned(result);
104 }
105
106 [[nodiscard]] static constexpr EmuDuration zero()
107 {
108 return EmuDuration(uint64_t(0));
109 }
110
111 [[nodiscard]] static constexpr EmuDuration infinity()
112 {
114 }
115
116 template<typename Archive>
117 void serialize(Archive& ar, unsigned /*version*/)
118 {
119 ar.serialize("time", time);
120 }
121
122private:
123 uint64_t time = 0;
124};
125
126template<> struct SerializeAsMemcpy<EmuDuration> : std::true_type {};
127
128
129template<std::unsigned_integral T> class EmuDurationCompactStorage
130{
131public:
133 : time(T(e.length()))
134 {
135 assert(e.length() <= std::numeric_limits<T>::max());
136 }
137
138 [[nodiscard]] constexpr operator EmuDuration() const
139 {
140 return EmuDuration(uint64_t(time));
141 }
142private:
143 T time;
144};
145
149
150namespace detail {
151 // via intermediate variable to work around gcc-10 warning
152 inline constexpr uint64_t max32 = std::numeric_limits<uint32_t>::max();
153 inline constexpr uint64_t max16 = std::numeric_limits<uint16_t>::max();
154 inline constexpr uint64_t max8 = std::numeric_limits<uint8_t >::max();
155}
156template<uint64_t MAX>
157using EmuDurationStorageFor = std::conditional_t<(MAX > detail::max32), EmuDuration,
158 std::conditional_t<(MAX > detail::max16), EmuDuration32,
159 std::conditional_t<(MAX > detail::max8 ), EmuDuration16,
160 EmuDuration8>>>;
161} // namespace openmsx
162
163#endif
constexpr EmuDurationCompactStorage(EmuDuration e)
Definition: EmuDuration.hh:132
void serialize(Archive &ar, unsigned)
Definition: EmuDuration.hh:117
static constexpr EmuDuration sec(unsigned x)
Definition: EmuDuration.hh:41
constexpr EmuDuration operator+(EmuDuration::param d) const
Definition: EmuDuration.hh:60
constexpr unsigned divUp(EmuDuration::param d) const
Definition: EmuDuration.hh:77
constexpr EmuDuration(double duration)
Definition: EmuDuration.hh:38
constexpr uint64_t length() const
Definition: EmuDuration.hh:52
constexpr EmuDuration operator/(unsigned fact) const
Definition: EmuDuration.hh:64
constexpr EmuDuration(uint64_t n)
Definition: EmuDuration.hh:37
constexpr EmuDuration()=default
constexpr EmuDuration & operator/=(double fact)
Definition: EmuDuration.hh:91
static constexpr EmuDuration infinity()
Definition: EmuDuration.hh:111
friend class EmuTime
Definition: EmuDuration.hh:33
static constexpr EmuDuration hz(unsigned x)
Definition: EmuDuration.hh:47
constexpr EmuDuration & operator*=(double fact)
Definition: EmuDuration.hh:89
constexpr EmuDuration divRoundUp(unsigned fact) const
Definition: EmuDuration.hh:66
static constexpr EmuDuration msec(unsigned x)
Definition: EmuDuration.hh:43
constexpr double toDouble() const
Definition: EmuDuration.hh:51
constexpr EmuDuration & operator*=(unsigned fact)
Definition: EmuDuration.hh:87
constexpr unsigned getTicksAt(unsigned freq) const
Definition: EmuDuration.hh:96
constexpr unsigned operator/(EmuDuration::param d) const
Definition: EmuDuration.hh:68
constexpr auto operator<=>(const EmuDuration &) const =default
static constexpr EmuDuration zero()
Definition: EmuDuration.hh:106
static constexpr EmuDuration usec(unsigned x)
Definition: EmuDuration.hh:45
constexpr EmuDuration operator%(EmuDuration::param d) const
Definition: EmuDuration.hh:58
constexpr double div(EmuDuration::param d) const
Definition: EmuDuration.hh:84
constexpr EmuDuration operator*(uint64_t fact) const
Definition: EmuDuration.hh:62
constexpr double e
Definition: Math.hh:21
Definition: join.hh:10
T length(const vecN< N, T > &x)
Definition: gl_vec.hh:341
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:285
constexpr uint64_t max16
Definition: EmuDuration.hh:153
constexpr uint64_t max8
Definition: EmuDuration.hh:154
constexpr uint64_t max32
Definition: EmuDuration.hh:152
This file implemented 3 utility functions:
Definition: Autofire.cc:9
EmuDurationCompactStorage< uint32_t > EmuDuration32
Definition: EmuDuration.hh:146
std::conditional_t<(MAX > detail::max32), EmuDuration, std::conditional_t<(MAX > detail::max16), EmuDuration32, std::conditional_t<(MAX > detail::max8), EmuDuration16, EmuDuration8 > > > EmuDurationStorageFor
Definition: EmuDuration.hh:160
constexpr unsigned MAIN_FREQ32
Definition: EmuDuration.hh:16
constexpr uint64_t MAIN_FREQ
Definition: EmuDuration.hh:15