openMSX
Clock.hh
Go to the documentation of this file.
1#ifndef CLOCK_HH
2#define CLOCK_HH
3
4#include "EmuDuration.hh"
5#include "EmuTime.hh"
6#include "DivModByConst.hh"
7#include "serialize.hh"
8#include <cassert>
9
10namespace openmsx {
11
17template<unsigned FREQ_NUM, unsigned FREQ_DENOM = 1>
18class Clock
19{
20private:
21 // stuff below calculates:
22 // MASTER_TICKS = MAIN_FREQ / (FREQ_NUM / FREQ_DENOM) + 0.5
23 static_assert(MAIN_FREQ < (1ULL << 32), "must fit in 32 bit");
24 static constexpr uint64_t P = MAIN_FREQ * FREQ_DENOM + (FREQ_NUM / 2);
25 static constexpr uint64_t MASTER_TICKS = P / FREQ_NUM;
26 static_assert(MASTER_TICKS < (1ULL << 32), "must fit in 32 bit");
27 static constexpr unsigned MASTER_TICKS32 = MASTER_TICKS;
28
29public:
30 // Note: default copy constructor and assignment operator are ok.
31
35 [[nodiscard]] static constexpr EmuDuration duration(unsigned ticks) {
36 return EmuDuration(ticks * MASTER_TICKS);
37 }
38
41 constexpr explicit Clock(EmuTime::param e)
42 : lastTick(e) { }
43
46 [[nodiscard]] constexpr EmuTime::param getTime() const { return lastTick; }
47
51 [[nodiscard]] constexpr bool before(EmuTime::param e) const {
52 return lastTick.time < e.time;
53 }
54
58 [[nodiscard]] constexpr unsigned getTicksTill(EmuTime::param e) const {
59 assert(e.time >= lastTick.time);
60 uint64_t result = (e.time - lastTick.time) / MASTER_TICKS;
61#ifdef DEBUG
62 // we don't even want this overhead in devel builds
63 assert(result == unsigned(result));
64#endif
65 return unsigned(result);
66 }
70 [[nodiscard]] constexpr unsigned getTicksTill_fast(EmuTime::param e) const {
71 assert(e.time >= lastTick.time);
73 return dm.div(e.time - lastTick.time);
74 }
79 [[nodiscard]] constexpr uint64_t getTicksTillUp(EmuTime::param e) const {
80 assert(e.time >= lastTick.time);
81 return (e.time - lastTick.time + MASTER_TICKS - 1) / MASTER_TICKS;
82 }
83
87 // TODO should be friend, workaround for pre-gcc-13 bug
88 [[nodiscard]] constexpr EmuTime operator+(uint64_t n) const {
89 return EmuTime(lastTick.time + n * MASTER_TICKS);
90 }
91
94 [[nodiscard]] constexpr EmuTime getFastAdd(unsigned n) const {
95 #ifdef DEBUG
96 assert((uint64_t(n) * MASTER_TICKS) < (1ULL << 32));
97 #endif
98 return EmuTime(lastTick.time + n * MASTER_TICKS);
99 }
100
103 constexpr void reset(EmuTime::param e) {
104 lastTick.time = e.time;
105 }
106
111 constexpr void advance(EmuTime::param e) {
112 assert(lastTick.time <= e.time);
113 lastTick.time = e.time - ((e.time - lastTick.time) % MASTER_TICKS);
114 }
118 constexpr void advance_fast(EmuTime::param e) {
119 assert(lastTick.time <= e.time);
121 lastTick.time = e.time - dm.mod(e.time - lastTick.time);
122 }
123
126 constexpr void operator+=(unsigned n) {
127 lastTick.time += n * MASTER_TICKS;
128 }
129
136 constexpr void fastAdd(unsigned n) {
137 #ifdef DEBUG
138 // we don't even want this overhead in development versions
139 assert((n * MASTER_TICKS) < (1ULL << 32));
140 #endif
141 lastTick.time += n * MASTER_TICKS32;
142 }
143
144 template<typename Archive>
145 void serialize(Archive& ar, unsigned /*version*/)
146 {
147 ar.serialize("lastTick", lastTick);
148 }
149
150private:
153 EmuTime lastTick;
154};
155
156template<unsigned FREQ_NUM, unsigned FREQ_DENOM>
157struct SerializeAsMemcpy<Clock<FREQ_NUM, FREQ_DENOM>> : std::true_type {};
158
159} // namespace openmsx
160
161#endif
Represents a clock with a fixed frequency.
Definition Clock.hh:19
constexpr uint64_t getTicksTillUp(EmuTime::param e) const
Calculate the number of ticks this clock has to tick to reach or go past the given time.
Definition Clock.hh:79
constexpr EmuTime operator+(uint64_t n) const
Calculate the time at which this clock will have ticked the given number of times (counted from its l...
Definition Clock.hh:88
constexpr Clock(EmuTime::param e)
Create a new clock, which starts ticking at the given time.
Definition Clock.hh:41
constexpr void advance_fast(EmuTime::param e)
Same as above, only faster, Though the time interval may not be too large.
Definition Clock.hh:118
constexpr void reset(EmuTime::param e)
Reset the clock to start ticking at the given time.
Definition Clock.hh:103
constexpr void operator+=(unsigned n)
Advance this clock by the given number of ticks.
Definition Clock.hh:126
static constexpr EmuDuration duration(unsigned ticks)
Calculates the duration of the given number of ticks at this clock's frequency.
Definition Clock.hh:35
void serialize(Archive &ar, unsigned)
Definition Clock.hh:145
constexpr EmuTime getFastAdd(unsigned n) const
Like operator+() but faster, though the step can't be too big (max a little over 1 second).
Definition Clock.hh:94
constexpr void fastAdd(unsigned n)
Advance this clock by the given number of ticks.
Definition Clock.hh:136
constexpr unsigned getTicksTill_fast(EmuTime::param e) const
Same as above, only faster, Though the time interval may not be too large.
Definition Clock.hh:70
constexpr bool before(EmuTime::param e) const
Checks whether this clock's last tick is or is not before the given time stamp.
Definition Clock.hh:51
constexpr EmuTime::param getTime() const
Gets the time at which the last clock tick occurred.
Definition Clock.hh:46
constexpr void advance(EmuTime::param e)
Advance this clock in time until the last tick which is not past the given time.
Definition Clock.hh:111
constexpr unsigned getTicksTill(EmuTime::param e) const
Calculate the number of ticks for this clock until the given time.
Definition Clock.hh:58
This file implemented 3 utility functions:
Definition Autofire.cc:11
constexpr uint64_t MAIN_FREQ
constexpr uint32_t div(uint64_t dividend) const
constexpr uint32_t mod(uint64_t dividend) const