diff --git a/ClockReceiver/ClockReceiver.hpp b/ClockReceiver/ClockReceiver.hpp index 482025d52..ba4a67629 100644 --- a/ClockReceiver/ClockReceiver.hpp +++ b/ClockReceiver/ClockReceiver.hpp @@ -149,8 +149,8 @@ template class WrappedInt { Flushes the value in @c this. The current value is returned, and the internal value is reset to zero. */ - forceinline T flush() { - T result(length_); + template forceinline Target flush() { + const Target result(length_); length_ = 0; return result; } @@ -185,8 +185,8 @@ class HalfCycles: public WrappedInt { } /// Flushes the whole cycles in @c this, subtracting that many from the total stored here. - forceinline Cycles flush_cycles() { - Cycles result(length_ >> 1); + template forceinline Cycles flush() { + const Cycles result(length_ >> 1); length_ &= 1; return result; } @@ -220,7 +220,7 @@ template class HalfClockReceiver: public T { forceinline void run_for(const HalfCycles half_cycles) { half_cycles_ += half_cycles; - T::run_for(half_cycles_.flush_cycles()); + T::run_for(half_cycles_.flush()); } private: diff --git a/ClockReceiver/ClockDeferrer.hpp b/ClockReceiver/DeferredQueue.hpp similarity index 85% rename from ClockReceiver/ClockDeferrer.hpp rename to ClockReceiver/DeferredQueue.hpp index cc41cbdd0..d2680f322 100644 --- a/ClockReceiver/ClockDeferrer.hpp +++ b/ClockReceiver/DeferredQueue.hpp @@ -1,26 +1,26 @@ // -// ClockDeferrer.hpp +// DeferredQueue.hpp // Clock Signal // // Created by Thomas Harte on 23/08/2018. // Copyright © 2018 Thomas Harte. All rights reserved. // -#ifndef ClockDeferrer_h -#define ClockDeferrer_h +#ifndef DeferredQueue_h +#define DeferredQueue_h #include #include /*! - A ClockDeferrer maintains a list of ordered actions and the times at which + A DeferredQueue maintains a list of ordered actions and the times at which they should happen, and divides a total execution period up into the portions that occur between those actions, triggering each action when it is reached. */ -template class ClockDeferrer { +template class DeferredQueue { public: - /// Constructs a ClockDeferrer that will call target(period) in between deferred actions. - ClockDeferrer(std::function &&target) : target_(std::move(target)) {} + /// Constructs a DeferredQueue that will call target(period) in between deferred actions. + DeferredQueue(std::function &&target) : target_(std::move(target)) {} /*! Schedules @c action to occur in @c delay units of time. @@ -79,4 +79,4 @@ template class ClockDeferrer { std::vector pending_actions_; }; -#endif /* ClockDeferrer_h */ +#endif /* DeferredQueue_h */ diff --git a/ClockReceiver/JustInTime.hpp b/ClockReceiver/JustInTime.hpp new file mode 100644 index 000000000..e9a3dd72b --- /dev/null +++ b/ClockReceiver/JustInTime.hpp @@ -0,0 +1,55 @@ +// +// JustInTime.hpp +// Clock Signal +// +// Created by Thomas Harte on 28/07/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#ifndef JustInTime_h +#define JustInTime_h + +//#include "../Concurrency/AsyncTaskQueue.hpp" + +/*! + A JustInTimeActor holds (i) an embedded object with a run_for method; and (ii) an amount + of time since run_for was last called. + + Time can be added using the += operator. The -> operator can be used to access the + embedded object. All time accumulated will be pushed to object before the pointer is returned. + + Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a + separate @c TargetTimeScale at template declaration. +*/ +template class JustInTimeActor { + public: + /// Constructs a new JustInTimeActor using the same construction arguments as the included object. + template JustInTimeActor(Args&&... args) : object_(std::forward(args)...) {} + + /// Adds time to the actor. + inline void operator += (const TimeScale &rhs) { + time_since_update_ += rhs; + } + + /// Flushes all accumulated time and returns a pointer to the included object. + inline T *operator->() { + object_.run_for(time_since_update_.template flush()); + return &object_; + } + + private: + T object_; + LocalTimeScale time_since_update_; + +}; + +/*! + A JustInTimeAsyncActor acts like a JustInTimeActor but additionally contains an AsyncTaskQueue. + Any time the amount of accumulated time crosses a threshold provided at construction time, + the object will be updated on the AsyncTaskQueue. +*/ +template class JustInTimeAsyncActor { + +}; + +#endif /* JustInTime_h */ diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp index 8a857c6ef..e39dec9da 100644 --- a/Machines/Apple/AppleII/AppleII.cpp +++ b/Machines/Apple/AppleII/AppleII.cpp @@ -77,7 +77,7 @@ template class ConcreteMachine: Cycles cycles_since_video_update_; void update_video() { - video_.run_for(cycles_since_video_update_.flush()); + video_.run_for(cycles_since_video_update_.flush()); } static const int audio_divider = 8; void update_audio() { diff --git a/Machines/Apple/AppleII/Video.hpp b/Machines/Apple/AppleII/Video.hpp index 7ae6b179b..e74b06c25 100644 --- a/Machines/Apple/AppleII/Video.hpp +++ b/Machines/Apple/AppleII/Video.hpp @@ -11,7 +11,7 @@ #include "../../../Outputs/CRT/CRT.hpp" #include "../../../ClockReceiver/ClockReceiver.hpp" -#include "../../../ClockReceiver/ClockDeferrer.hpp" +#include "../../../ClockReceiver/DeferredQueue.hpp" #include #include @@ -251,8 +251,8 @@ class VideoBase { */ void output_fat_low_resolution(uint8_t *target, const uint8_t *source, size_t length, int column, int row) const; - // Maintain a ClockDeferrer for delayed mode switches. - ClockDeferrer deferrer_; + // Maintain a DeferredQueue for delayed mode switches. + DeferredQueue deferrer_; }; template class Video: public VideoBase { diff --git a/Machines/Apple/Macintosh/DeferredAudio.hpp b/Machines/Apple/Macintosh/DeferredAudio.hpp index 72ebc6b10..6fda448fa 100644 --- a/Machines/Apple/Macintosh/DeferredAudio.hpp +++ b/Machines/Apple/Macintosh/DeferredAudio.hpp @@ -24,7 +24,7 @@ struct DeferredAudio { DeferredAudio() : audio(queue), speaker(audio) {} void flush() { - speaker.run_for(queue, time_since_update.flush_cycles()); + speaker.run_for(queue, time_since_update.flush()); } }; diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index 802288ad9..44c84a3e9 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -24,6 +24,8 @@ #include "../../../Inputs/QuadratureMouse/QuadratureMouse.hpp" #include "../../../Outputs/Log.hpp" +#include "../../../ClockReceiver/JustInTime.hpp" + //#define LOG_TRACE #include "../../../Components/6522/6522.hpp" @@ -471,7 +473,7 @@ template class ConcreteMachin Apple::IWM iwm; void flush() { - iwm.run_for(time_since_update.flush_cycles()); + iwm.run_for(time_since_update.flush()); } }; @@ -610,7 +612,6 @@ template class ConcreteMachin HalfCycles keyboard_clock_; HalfCycles time_since_video_update_; HalfCycles time_until_video_event_; - HalfCycles time_since_iwm_update_; HalfCycles time_since_mouse_update_; bool ROM_is_overlay_ = true; diff --git a/Machines/Atari2600/Bus.hpp b/Machines/Atari2600/Bus.hpp index ba58c81c5..efcb05091 100644 --- a/Machines/Atari2600/Bus.hpp +++ b/Machines/Atari2600/Bus.hpp @@ -55,13 +55,13 @@ class Bus { // video backlog accumulation counter Cycles cycles_since_video_update_; inline void update_video() { - tia_.run_for(cycles_since_video_update_.flush()); + tia_.run_for(cycles_since_video_update_.flush()); } // RIOT backlog accumulation counter Cycles cycles_since_6532_update_; inline void update_6532() { - mos6532_.run_for(cycles_since_6532_update_.flush()); + mos6532_.run_for(cycles_since_6532_update_.flush()); } }; diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 2ac58a2e5..4c65dc304 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -702,7 +702,7 @@ class ConcreteMachine: private: void update_video() { - mos6560_.run_for(cycles_since_mos6560_update_.flush()); + mos6560_.run_for(cycles_since_mos6560_update_.flush()); } CPU::MOS6502::Processor m6502_; diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index f0a31815e..e87f2641f 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -510,7 +510,7 @@ class ConcreteMachine: // MARK: - Work deferral updates. inline void update_display() { if(cycles_since_display_update_ > 0) { - video_output_.run_for(cycles_since_display_update_.flush()); + video_output_.run_for(cycles_since_display_update_.flush()); } } diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index b90ce9fd8..158acc11e 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -182,7 +182,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler { private: void update_ay() { - speaker_.run_for(audio_queue_, cycles_since_ay_update_.flush_cycles()); + speaker_.run_for(audio_queue_, cycles_since_ay_update_.flush()); } bool ay_bdir_ = false; bool ay_bc1_ = false; @@ -585,7 +585,7 @@ template class Co uint8_t ram_[65536]; Cycles cycles_since_video_update_; inline void update_video() { - video_output_.run_for(cycles_since_video_update_.flush()); + video_output_.run_for(cycles_since_video_update_.flush()); } // ROM bookkeeping @@ -617,7 +617,7 @@ template class Co Apple::DiskII diskii_; Cycles cycles_since_diskii_update_; void flush_diskii() { - diskii_.run_for(cycles_since_diskii_update_.flush()); + diskii_.run_for(cycles_since_diskii_update_.flush()); } std::vector pravetz_rom_; std::size_t pravetz_rom_base_pointer_ = 0; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index d43ce8c20..c5ea334a6 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -983,6 +983,7 @@ 4B7F188D2154825D00388727 /* MasterSystem.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MasterSystem.hpp; sourceTree = ""; }; 4B7F1895215486A100388727 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = ""; }; 4B7F1896215486A100388727 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; + 4B80214322EE7C3E00068002 /* JustInTime.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = JustInTime.hpp; sourceTree = ""; }; 4B80ACFE1F85CAC900176895 /* BestEffortUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BestEffortUpdater.cpp; path = ../../Concurrency/BestEffortUpdater.cpp; sourceTree = ""; }; 4B80ACFF1F85CACA00176895 /* BestEffortUpdater.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = BestEffortUpdater.hpp; path = ../../Concurrency/BestEffortUpdater.hpp; sourceTree = ""; }; 4B8334811F5D9FF70097E338 /* PartialMachineCycle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PartialMachineCycle.cpp; sourceTree = ""; }; @@ -1051,7 +1052,7 @@ 4B894516201967B4007DE474 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; 4B894517201967B4007DE474 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; 4B894540201967D6007DE474 /* Machines.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Machines.hpp; sourceTree = ""; }; - 4B8A7E85212F988200F2BBC6 /* ClockDeferrer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ClockDeferrer.hpp; sourceTree = ""; }; + 4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DeferredQueue.hpp; sourceTree = ""; }; 4B8D287E1F77207100645199 /* TrackSerialiser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TrackSerialiser.hpp; sourceTree = ""; }; 4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = KeyboardMachine.hpp; sourceTree = ""; }; 4B8EF6071FE5AF830076CCDD /* LowpassSpeaker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LowpassSpeaker.hpp; sourceTree = ""; }; @@ -3383,10 +3384,11 @@ 4BF660691F281573002CB053 /* ClockReceiver */ = { isa = PBXGroup; children = ( - 4B8A7E85212F988200F2BBC6 /* ClockDeferrer.hpp */, 4BB146C61F49D7D700253439 /* ClockingHintSource.hpp */, 4BF6606A1F281573002CB053 /* ClockReceiver.hpp */, + 4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */, 4BB06B211F316A3F00600C7A /* ForceInline.hpp */, + 4B80214322EE7C3E00068002 /* JustInTime.hpp */, 4B449C942063389900A095C8 /* TimeTypes.hpp */, ); name = ClockReceiver;