1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-09 01:29:44 +00:00

Start experimenting with a more event-based approach to timing.

This commit is contained in:
Thomas Harte 2022-07-07 10:48:42 -04:00
parent 18735ee571
commit 7886c2df7a
3 changed files with 88 additions and 0 deletions

View File

@ -0,0 +1,77 @@
//
// AsyncUpdater.h
// Clock Signal
//
// Created by Thomas Harte on 06/07/2022.
// Copyright © 2022 Thomas Harte. All rights reserved.
//
#ifndef AsyncUpdater_hpp
#define AsyncUpdater_hpp
#include <atomic>
#include <condition_variable>
#include <mutex>
#include "../ClockReceiver/TimeTypes.hpp"
namespace Concurrency {
template <typename Performer> class AsyncUpdater {
public:
template <typename... Args> AsyncUpdater(Args&&... args)
: performer_(std::forward<Args>(args)...),
performer_thread_{
[this] {
Time::Nanos last_fired = Time::nanos_now();
while(!should_quit) {
// Wait for a new action to be signalled, and grab it.
std::unique_lock lock(condition_mutex_);
while(actions_.empty()) {
condition_.wait(lock);
}
auto action = actions_.pop_back();
lock.unlock();
// Update to now.
auto time_now = Time::nanos_now();
performer_.perform(time_now - last_fired);
last_fired = time_now;
// Perform the action.
action();
}
}
} {}
/// Run the performer up to 'now' and then perform @c post_action.
///
/// @c post_action will be performed asynchronously, on the same
/// thread as the performer.
void update(const std::function<void(void)> &post_action) {
std::lock_guard guard(condition_mutex_);
actions_.push_back(post_action);
condition_.notify_all();
}
~AsyncUpdater() {
should_quit = true;
update([] {});
performer_thread_.join();
}
private:
Performer performer_;
std::thread performer_thread_;
std::mutex condition_mutex_;
std::condition_variable condition_;
std::vector<std::function<void(void)>> actions_;
std::atomic<bool> should_quit = false;
};
}
#endif /* AsyncUpdater_hpp */

View File

@ -2138,6 +2138,7 @@
4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = "<group>"; };
4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = "<group>"; };
4BE0151C286A8C8E00EA42E9 /* MemorySwitches.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MemorySwitches.hpp; sourceTree = "<group>"; };
4BE0151E28766ECF00EA42E9 /* AsyncUpdater.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AsyncUpdater.hpp; sourceTree = "<group>"; };
4BE0A3EC237BB170002AB46F /* ST.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ST.cpp; sourceTree = "<group>"; };
4BE0A3ED237BB170002AB46F /* ST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ST.hpp; sourceTree = "<group>"; };
4BE211DD253E4E4800435408 /* 65C02_no_Rockwell_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = 65C02_no_Rockwell_test.bin; path = "Klaus Dormann/65C02_no_Rockwell_test.bin"; sourceTree = "<group>"; };
@ -2754,6 +2755,7 @@
children = (
4B3940E51DA83C8300427841 /* AsyncTaskQueue.cpp */,
4B3940E61DA83C8300427841 /* AsyncTaskQueue.hpp */,
4BE0151E28766ECF00EA42E9 /* AsyncUpdater.hpp */,
);
name = Concurrency;
path = ../../Concurrency;

View File

@ -24,6 +24,7 @@
#include "../../../../ClockReceiver/TimeTypes.hpp"
#include "../../../../ClockReceiver/ScanSynchroniser.hpp"
#include "../../../../Concurrency/AsyncUpdater.hpp"
#import "CSStaticAnalyser+TargetVector.h"
#import "NSBundle+DataResource.h"
@ -34,6 +35,14 @@
#include <codecvt>
#include <locale>
namespace {
struct Updater {};
Concurrency::AsyncUpdater<Updater> updater();
}
@interface CSMachine() <CSScanTargetViewDisplayLinkDelegate>
- (void)speaker:(Outputs::Speaker::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length;
- (void)speakerDidChangeInputClock:(Outputs::Speaker::Speaker *)speaker;