mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-21 20:29:06 +00:00
Resolve crash of machines that require the ROM requester.
This commit is contained in:
parent
38a509bc20
commit
1b197d0bb2
@ -65,34 +65,14 @@ template <> struct TaskQueueStorage<void> {
|
|||||||
action occupies the asynchronous thread for long enough. So it is not true that @c perform will be
|
action occupies the asynchronous thread for long enough. So it is not true that @c perform will be
|
||||||
called once per action.
|
called once per action.
|
||||||
*/
|
*/
|
||||||
template <bool perform_automatically, typename Performer = void> class AsyncTaskQueue: public TaskQueueStorage<Performer> {
|
template <bool perform_automatically, bool start_immediately = true, typename Performer = void> class AsyncTaskQueue: public TaskQueueStorage<Performer> {
|
||||||
public:
|
public:
|
||||||
template <typename... Args> AsyncTaskQueue(Args&&... args) :
|
template <typename... Args> AsyncTaskQueue(Args&&... args) :
|
||||||
TaskQueueStorage<Performer>(std::forward<Args>(args)...),
|
TaskQueueStorage<Performer>(std::forward<Args>(args)...) {
|
||||||
thread_{
|
if constexpr (start_immediately) {
|
||||||
[this] {
|
start();
|
||||||
ActionVector actions;
|
}
|
||||||
|
}
|
||||||
while(!should_quit_) {
|
|
||||||
// Wait for new actions to be signalled, and grab them.
|
|
||||||
std::unique_lock lock(condition_mutex_);
|
|
||||||
while(actions_.empty()) {
|
|
||||||
condition_.wait(lock);
|
|
||||||
}
|
|
||||||
std::swap(actions, actions_);
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
// Update to now (which is possibly a no-op).
|
|
||||||
TaskQueueStorage<Performer>::update();
|
|
||||||
|
|
||||||
// Perform the actions and destroy them.
|
|
||||||
for(const auto &action: actions) {
|
|
||||||
action();
|
|
||||||
}
|
|
||||||
actions.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} {}
|
|
||||||
|
|
||||||
/// Enqueus @c post_action to be performed asynchronously at some point
|
/// Enqueus @c post_action to be performed asynchronously at some point
|
||||||
/// in the future. If @c perform_automatically is @c true then the action
|
/// in the future. If @c perform_automatically is @c true then the action
|
||||||
@ -136,6 +116,37 @@ template <bool perform_automatically, typename Performer = void> class AsyncTask
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Starts the queue if it has never been started before.
|
||||||
|
///
|
||||||
|
/// This is not guaranteed safely to restart a stopped queue.
|
||||||
|
void start() {
|
||||||
|
thread_ = std::move(std::thread{
|
||||||
|
[this] {
|
||||||
|
ActionVector actions;
|
||||||
|
|
||||||
|
// Continue until told to quit.
|
||||||
|
while(!should_quit_) {
|
||||||
|
// Wait for new actions to be signalled, and grab them.
|
||||||
|
std::unique_lock lock(condition_mutex_);
|
||||||
|
while(actions_.empty()) {
|
||||||
|
condition_.wait(lock);
|
||||||
|
}
|
||||||
|
std::swap(actions, actions_);
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
// Update to now (which is possibly a no-op).
|
||||||
|
TaskQueueStorage<Performer>::update();
|
||||||
|
|
||||||
|
// Perform the actions and destroy them.
|
||||||
|
for(const auto &action: actions) {
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
actions.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Schedules any remaining unscheduled work, then blocks synchronously
|
/// Schedules any remaining unscheduled work, then blocks synchronously
|
||||||
/// until all scheduled work has been performed.
|
/// until all scheduled work has been performed.
|
||||||
void flush() {
|
void flush() {
|
||||||
|
@ -122,7 +122,7 @@ struct ActivityObserver: public Activity::Observer {
|
|||||||
CSJoystickManager *_joystickManager;
|
CSJoystickManager *_joystickManager;
|
||||||
NSMutableArray<CSMachineLED *> *_leds;
|
NSMutableArray<CSMachineLED *> *_leds;
|
||||||
|
|
||||||
Concurrency::AsyncTaskQueue<true, MachineUpdater> updater;
|
Concurrency::AsyncTaskQueue<true, false, MachineUpdater> updater;
|
||||||
Time::ScanSynchroniser _scanSynchroniser;
|
Time::ScanSynchroniser _scanSynchroniser;
|
||||||
|
|
||||||
NSTimer *_joystickTimer;
|
NSTimer *_joystickTimer;
|
||||||
@ -149,6 +149,9 @@ struct ActivityObserver: public Activity::Observer {
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
updater.performer.machine = _machine->timed_machine();
|
updater.performer.machine = _machine->timed_machine();
|
||||||
|
if(updater.performer.machine) {
|
||||||
|
updater.start();
|
||||||
|
}
|
||||||
|
|
||||||
// Use the keyboard as a joystick if the machine has no keyboard, or if it has a 'non-exclusive' keyboard.
|
// Use the keyboard as a joystick if the machine has no keyboard, or if it has a 'non-exclusive' keyboard.
|
||||||
_inputMode =
|
_inputMode =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user