mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Start experimenting with a more event-based approach to timing.
This commit is contained in:
parent
18735ee571
commit
7886c2df7a
77
Concurrency/AsyncUpdater.hpp
Normal file
77
Concurrency/AsyncUpdater.hpp
Normal 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 */
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user