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