openMSX
EmuDuration.hh
Go to the documentation of this file.
1 #ifndef EMUDURATION_HH
2 #define EMUDURATION_HH
3 
4 #include "serialize.hh"
5 #include <cassert>
6 #include <concepts>
7 #include <cstdint>
8 #include <limits>
9 #include <type_traits>
10 
11 namespace openmsx {
12 
13 // constants
14 constexpr uint64_t MAIN_FREQ = 3579545ULL * 960;
15 constexpr unsigned MAIN_FREQ32 = MAIN_FREQ;
16 static_assert(MAIN_FREQ < (1ull << 32), "must fit in 32 bit");
17 
18 
20 {
21 public:
22  // This is only a very small class (one 64-bit member). On 64-bit CPUs
23  // it's cheaper to pass this by value. On 32-bit CPUs pass-by-reference
24  // is cheaper.
25 #ifdef __x86_64
26  using param = EmuDuration;
27 #else
28  using param = const EmuDuration&;
29 #endif
30 
31  // friends
32  friend class EmuTime;
33 
34  // constructors
35  constexpr EmuDuration() = default;
36  constexpr explicit EmuDuration(uint64_t n) : time(n) {}
37  constexpr explicit EmuDuration(double duration)
38  : time(uint64_t(duration * MAIN_FREQ + 0.5)) {}
39 
40  static constexpr EmuDuration sec(unsigned x)
41  { return EmuDuration(x * MAIN_FREQ); }
42  static constexpr EmuDuration msec(unsigned x)
43  { return EmuDuration(x * MAIN_FREQ / 1000); }
44  static constexpr EmuDuration usec(unsigned x)
45  { return EmuDuration(x * MAIN_FREQ / 1000000); }
46  static constexpr EmuDuration hz(unsigned x)
47  { return EmuDuration(MAIN_FREQ / x); }
48 
49  // conversions
50  [[nodiscard]] constexpr double toDouble() const { return double(time) / MAIN_FREQ32; }
51  [[nodiscard]] constexpr uint64_t length() const { return time; }
52 
53  // comparison operators
54  [[nodiscard]] constexpr bool operator== (const EmuDuration&) const = default;
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 double(time) / d.time; }
86 
87  constexpr EmuDuration& operator*=(unsigned fact)
88  { time *= fact; return *this; }
89  constexpr EmuDuration& operator*=(double fact)
90  { time = uint64_t(time * fact); return *this; }
91  constexpr EmuDuration& operator/=(double fact)
92  { time = uint64_t(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 
122 private:
123  uint64_t time = 0;
124 };
125 
126 template<> struct SerializeAsMemcpy<EmuDuration> : std::true_type {};
127 
128 
129 template<std::unsigned_integral T> class EmuDurationCompactStorage
130 {
131 public:
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  }
142 private:
143  T time;
144 };
145 
149 
150 namespace 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 }
156 template<uint64_t MAX>
157 using 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:40
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:37
constexpr bool operator==(const EmuDuration &) const =default
constexpr uint64_t length() const
Definition: EmuDuration.hh:51
constexpr EmuDuration operator/(unsigned fact) const
Definition: EmuDuration.hh:64
constexpr EmuDuration & operator*=(double fact)
Definition: EmuDuration.hh:89
constexpr EmuDuration(uint64_t n)
Definition: EmuDuration.hh:36
constexpr EmuDuration()=default
static constexpr EmuDuration infinity()
Definition: EmuDuration.hh:111
constexpr EmuDuration & operator*=(unsigned fact)
Definition: EmuDuration.hh:87
friend class EmuTime
Definition: EmuDuration.hh:32
static constexpr EmuDuration hz(unsigned x)
Definition: EmuDuration.hh:46
constexpr EmuDuration divRoundUp(unsigned fact) const
Definition: EmuDuration.hh:66
static constexpr EmuDuration msec(unsigned x)
Definition: EmuDuration.hh:42
constexpr double toDouble() const
Definition: EmuDuration.hh:50
constexpr EmuDuration & operator/=(double fact)
Definition: EmuDuration.hh:91
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:44
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:18
Definition: join.hh:10
T length(const vecN< N, T > &x)
Definition: gl_vec.hh:339
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:283
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:15
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:127
constexpr uint64_t MAIN_FREQ
Definition: EmuDuration.hh:14