mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Merge pull request #1086 from TomHarte/AmigaCrash
Resolve crash of machines that require the ROM requester under macOS.
This commit is contained in:
commit
1a68df6765
@ -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
|
||||
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:
|
||||
template <typename... Args> AsyncTaskQueue(Args&&... args) :
|
||||
TaskQueueStorage<Performer>(std::forward<Args>(args)...),
|
||||
thread_{
|
||||
[this] {
|
||||
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();
|
||||
}
|
||||
}
|
||||
} {}
|
||||
TaskQueueStorage<Performer>(std::forward<Args>(args)...) {
|
||||
if constexpr (start_immediately) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
/// Enqueus @c post_action to be performed asynchronously at some point
|
||||
/// 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
|
||||
/// until all scheduled work has been performed.
|
||||
void flush() {
|
||||
|
@ -122,7 +122,7 @@ struct ActivityObserver: public Activity::Observer {
|
||||
CSJoystickManager *_joystickManager;
|
||||
NSMutableArray<CSMachineLED *> *_leds;
|
||||
|
||||
Concurrency::AsyncTaskQueue<true, MachineUpdater> updater;
|
||||
Concurrency::AsyncTaskQueue<true, false, MachineUpdater> updater;
|
||||
Time::ScanSynchroniser _scanSynchroniser;
|
||||
|
||||
NSTimer *_joystickTimer;
|
||||
@ -149,6 +149,9 @@ struct ActivityObserver: public Activity::Observer {
|
||||
return nil;
|
||||
}
|
||||
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.
|
||||
_inputMode =
|
||||
|
Loading…
Reference in New Issue
Block a user