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 [[nodiscard]] constexpr EmuTime operator+(uint64_t n) const {
88 return EmuTime(lastTick.time + n * MASTER_TICKS);
89 }
90
93 [[nodiscard]] constexpr EmuTime getFastAdd(unsigned n) const {
94 #ifdef DEBUG
95 assert((uint64_t(n) * MASTER_TICKS) < (1ull << 32));
96 #endif
97 return EmuTime(lastTick.time + n * MASTER_TICKS);
98 }
99
102 constexpr void reset(EmuTime::param e) {
103 lastTick.time = e.time;
104 }
105
110 constexpr void advance(EmuTime::param e) {
111 assert(lastTick.time <= e.time);
112 lastTick.time = e.time - ((e.time - lastTick.time) % MASTER_TICKS);
113 }
117 constexpr void advance_fast(EmuTime::param e) {
118 assert(lastTick.time <= e.time);
120 lastTick.time = e.time - dm.mod(e.time - lastTick.time);
121 }
122
125 constexpr void operator+=(unsigned n) {
126 lastTick.time += n * MASTER_TICKS;
127 }
128
135 constexpr void fastAdd(unsigned n) {
136 #ifdef DEBUG
137 // we don't even want this overhead in development versions
138 assert((n * MASTER_TICKS) < (1ull << 32));
139 #endif
140 lastTick.time += n * MASTER_TICKS32;
141 }
142
143 template<typename Archive>
144 void serialize(Archive& ar, unsigned /*version*/)
145 {
146 ar.serialize("lastTick", lastTick);
147 }
148
149private:
152 EmuTime lastTick;
153};
154
155template<unsigned FREQ_NUM, unsigned FREQ_DENOM>
156struct SerializeAsMemcpy<Clock<FREQ_NUM, FREQ_DENOM>> : std::true_type {};
157
158} // namespace openmsx
159
160#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:87
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:117
constexpr void reset(EmuTime::param e)
Reset the clock to start ticking at the given time.
Definition: Clock.hh:102
constexpr void operator+=(unsigned n)
Advance this clock by the given number of ticks.
Definition: Clock.hh:125
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:144
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:93
constexpr void fastAdd(unsigned n)
Advance this clock by the given number of ticks.
Definition: Clock.hh:135
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:110
constexpr unsigned getTicksTill(EmuTime::param e) const
Calculate the number of ticks for this clock until the given time.
Definition: Clock.hh:58
constexpr double e
Definition: Math.hh:20
This file implemented 3 utility functions:
Definition: Autofire.cc:9
constexpr uint64_t MAIN_FREQ
Definition: EmuDuration.hh:15
constexpr uint32_t div(uint64_t dividend) const
constexpr uint32_t mod(uint64_t dividend) const