1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Ensures video interrupts can't be missed by a suitably-timed access.

This commit is contained in:
Thomas Harte 2020-11-26 16:11:03 -05:00
parent 72884f37c3
commit 8093f67173
2 changed files with 16 additions and 9 deletions

View File

@ -96,7 +96,7 @@ template <class T, int multiplier = 1, int divider = 1, class LocalTimeScale = H
/// This does not affect this actor's record of when the next sequence point will occur. /// This does not affect this actor's record of when the next sequence point will occur.
forceinline void flush() { forceinline void flush() {
if(!is_flushed_) { if(!is_flushed_) {
is_flushed_ = true; did_flush_ = is_flushed_ = true;
if constexpr (divider == 1) { if constexpr (divider == 1) {
const auto duration = time_since_update_.template flush<TargetTimeScale>(); const auto duration = time_since_update_.template flush<TargetTimeScale>();
object_.run_for(duration); object_.run_for(duration);
@ -108,12 +108,11 @@ template <class T, int multiplier = 1, int divider = 1, class LocalTimeScale = H
} }
} }
/// Indicates whether a sequence-point-caused flush will occur if the specified period is added. /// Indicates whether a flush has occurred since the last call to did_flush().
forceinline bool will_flush(LocalTimeScale rhs) const { forceinline bool did_flush() {
if constexpr (!has_sequence_points<T>::value) { const bool did_flush = did_flush_;
return false; did_flush_ = false;
} return did_flush;
return rhs >= time_until_event_;
} }
/// @returns the number of cycles until the next sequence-point-based flush, if the embedded object /// @returns the number of cycles until the next sequence-point-based flush, if the embedded object
@ -122,6 +121,14 @@ template <class T, int multiplier = 1, int divider = 1, class LocalTimeScale = H
return time_until_event_; return time_until_event_;
} }
/// Indicates whether a sequence-point-caused flush will occur if the specified period is added.
forceinline bool will_flush(LocalTimeScale rhs) const {
if constexpr (!has_sequence_points<T>::value) {
return false;
}
return rhs >= time_until_event_;
}
/// Updates this template's record of the next sequence point. /// Updates this template's record of the next sequence point.
void update_sequence_point() { void update_sequence_point() {
if constexpr (has_sequence_points<T>::value) { if constexpr (has_sequence_points<T>::value) {
@ -134,6 +141,7 @@ template <class T, int multiplier = 1, int divider = 1, class LocalTimeScale = H
T object_; T object_;
LocalTimeScale time_since_update_, time_until_event_; LocalTimeScale time_since_update_, time_until_event_;
bool is_flushed_ = true; bool is_flushed_ = true;
bool did_flush_ = false;
template <typename S, typename = void> struct has_sequence_points : std::false_type {}; template <typename S, typename = void> struct has_sequence_points : std::false_type {};
template <typename S> struct has_sequence_points<S, decltype(void(std::declval<S &>().get_next_sequence_point()))> : std::true_type {}; template <typename S> struct has_sequence_points<S, decltype(void(std::declval<S &>().get_next_sequence_point()))> : std::true_type {};

View File

@ -719,13 +719,12 @@ class ConcreteMachine:
update_interrupts(); update_interrupts();
} }
const bool will_flush_video = video_.will_flush(duration);
video_ += duration; video_ += duration;
iwm_ += duration; iwm_ += duration;
cycles_since_audio_update_ += duration; cycles_since_audio_update_ += duration;
total += decltype(total)(duration.as_integral()); total += decltype(total)(duration.as_integral());
if(will_flush_video) { if(video_.did_flush()) {
update_interrupts(); update_interrupts();
} }