1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-29 12:50:28 +00:00

Ensures thread safety of access to machines array.

This commit is contained in:
Thomas Harte 2018-02-10 19:38:26 -05:00
parent eb39617ad0
commit e1cab52c84
7 changed files with 39 additions and 22 deletions

View File

@ -13,15 +13,18 @@
using namespace Analyser::Dynamic; using namespace Analyser::Dynamic;
MultiCRTMachine::MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) : MultiCRTMachine::MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines, std::mutex &machines_mutex) :
machines_(machines), queues_(machines.size()) {} machines_(machines), machines_mutex_(machines_mutex), queues_(machines.size()) {}
void MultiCRTMachine::perform_parallel(const std::function<void(::CRTMachine::Machine *)> &function) { void MultiCRTMachine::perform_parallel(const std::function<void(::CRTMachine::Machine *)> &function) {
// Apply a blunt force parallelisation of the machines; each run_for is dispatched // Apply a blunt force parallelisation of the machines; each run_for is dispatched
// to a separate queue and this queue will block until all are done. // to a separate queue and this queue will block until all are done.
volatile std::size_t outstanding_machines;
std::condition_variable condition; std::condition_variable condition;
std::mutex mutex; std::mutex mutex;
std::size_t outstanding_machines = machines_.size(); {
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
outstanding_machines = machines_.size();
for(std::size_t index = 0; index < machines_.size(); ++index) { for(std::size_t index = 0; index < machines_.size(); ++index) {
queues_[index].enqueue([&mutex, &condition, this, index, function, &outstanding_machines]() { queues_[index].enqueue([&mutex, &condition, this, index, function, &outstanding_machines]() {
@ -33,6 +36,7 @@ void MultiCRTMachine::perform_parallel(const std::function<void(::CRTMachine::Ma
condition.notify_all(); condition.notify_all();
}); });
} }
}
while(true) { while(true) {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
@ -42,6 +46,7 @@ void MultiCRTMachine::perform_parallel(const std::function<void(::CRTMachine::Ma
} }
void MultiCRTMachine::perform_serial(const std::function<void (::CRTMachine::Machine *)> &function) { void MultiCRTMachine::perform_serial(const std::function<void (::CRTMachine::Machine *)> &function) {
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
for(const auto &machine: machines_) { for(const auto &machine: machines_) {
CRTMachine::Machine *crt_machine = machine->crt_machine(); CRTMachine::Machine *crt_machine = machine->crt_machine();
if(crt_machine) function(crt_machine); if(crt_machine) function(crt_machine);
@ -61,11 +66,13 @@ void MultiCRTMachine::close_output() {
} }
Outputs::CRT::CRT *MultiCRTMachine::get_crt() { Outputs::CRT::CRT *MultiCRTMachine::get_crt() {
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine(); CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
return crt_machine ? crt_machine->get_crt() : nullptr; return crt_machine ? crt_machine->get_crt() : nullptr;
} }
Outputs::Speaker::Speaker *MultiCRTMachine::get_speaker() { Outputs::Speaker::Speaker *MultiCRTMachine::get_speaker() {
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine(); CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
return crt_machine ? crt_machine->get_speaker() : nullptr; return crt_machine ? crt_machine->get_speaker() : nullptr;
} }
@ -80,11 +87,13 @@ void MultiCRTMachine::run_for(const Cycles cycles) {
double MultiCRTMachine::get_clock_rate() { double MultiCRTMachine::get_clock_rate() {
// TODO: something smarter than this? Not all clock rates will necessarily be the same. // TODO: something smarter than this? Not all clock rates will necessarily be the same.
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine(); CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
return crt_machine ? crt_machine->get_clock_rate() : 0.0; return crt_machine ? crt_machine->get_clock_rate() : 0.0;
} }
bool MultiCRTMachine::get_clock_is_unlimited() { bool MultiCRTMachine::get_clock_is_unlimited() {
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine(); CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
return crt_machine ? crt_machine->get_clock_is_unlimited() : false; return crt_machine ? crt_machine->get_clock_is_unlimited() : false;
} }

View File

@ -14,6 +14,7 @@
#include "../../../../Machines/DynamicMachine.hpp" #include "../../../../Machines/DynamicMachine.hpp"
#include <memory> #include <memory>
#include <mutex>
#include <vector> #include <vector>
namespace Analyser { namespace Analyser {
@ -21,7 +22,7 @@ namespace Dynamic {
class MultiCRTMachine: public ::CRTMachine::Machine, public ::CRTMachine::Machine::Delegate { class MultiCRTMachine: public ::CRTMachine::Machine, public ::CRTMachine::Machine::Delegate {
public: public:
MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines); MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines, std::mutex &machines_mutex);
void setup_output(float aspect_ratio) override; void setup_output(float aspect_ratio) override;
void close_output() override; void close_output() override;
@ -46,6 +47,7 @@ class MultiCRTMachine: public ::CRTMachine::Machine, public ::CRTMachine::Machin
private: private:
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_; const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_;
std::mutex &machines_mutex_;
std::vector<Concurrency::AsyncTaskQueue> queues_; std::vector<Concurrency::AsyncTaskQueue> queues_;
Delegate *delegate_ = nullptr; Delegate *delegate_ = nullptr;

View File

@ -10,19 +10,20 @@
using namespace Analyser::Dynamic; using namespace Analyser::Dynamic;
MultiConfigurationTarget::MultiConfigurationTarget(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) : MultiConfigurationTarget::MultiConfigurationTarget(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) {
machines_(machines) {} for(const auto &machine: machines) {
ConfigurationTarget::Machine *configuration_target = machine->configuration_target();
if(configuration_target) targets_.push_back(configuration_target);
}
}
void MultiConfigurationTarget::configure_as_target(const Analyser::Static::Target &target) { void MultiConfigurationTarget::configure_as_target(const Analyser::Static::Target &target) {
} }
bool MultiConfigurationTarget::insert_media(const Analyser::Static::Media &media) { bool MultiConfigurationTarget::insert_media(const Analyser::Static::Media &media) {
bool inserted = false; bool inserted = false;
for(const auto &machine : machines_) { for(const auto &target : targets_) {
ConfigurationTarget::Machine *configuration_target = machine->configuration_target(); inserted |= target->insert_media(media);
if(configuration_target) {
inserted |= configuration_target->insert_media(media);
}
} }
return inserted; return inserted;
} }

View File

@ -18,7 +18,7 @@
namespace Analyser { namespace Analyser {
namespace Dynamic { namespace Dynamic {
struct MultiConfigurationTarget: public ::ConfigurationTarget::Machine { struct MultiConfigurationTarget: public ConfigurationTarget::Machine {
public: public:
MultiConfigurationTarget(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines); MultiConfigurationTarget(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
@ -26,7 +26,7 @@ struct MultiConfigurationTarget: public ::ConfigurationTarget::Machine {
bool insert_media(const Analyser::Static::Media &media) override; bool insert_media(const Analyser::Static::Media &media) override;
private: private:
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_; std::vector<ConfigurationTarget::Machine *> targets_;
}; };
} }

View File

@ -14,7 +14,7 @@ MultiMachine::MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machin
machines_(std::move(machines)), machines_(std::move(machines)),
configurable_(machines_), configurable_(machines_),
configuration_target_(machines_), configuration_target_(machines_),
crt_machine_(machines_), crt_machine_(machines_, machines_mutex_),
joystick_machine_(machines), joystick_machine_(machines),
keyboard_machine_(machines_) { keyboard_machine_(machines_) {
crt_machine_.set_delegate(this); crt_machine_.set_delegate(this);
@ -41,6 +41,7 @@ Configurable::Device *MultiMachine::configurable_device() {
} }
void MultiMachine::multi_crt_did_run_machines() { void MultiMachine::multi_crt_did_run_machines() {
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
DynamicMachine *front = machines_.front().get(); DynamicMachine *front = machines_.front().get();
// for(const auto &machine: machines_) { // for(const auto &machine: machines_) {
// CRTMachine::Machine *crt = machine->crt_machine(); // CRTMachine::Machine *crt = machine->crt_machine();
@ -49,6 +50,7 @@ void MultiMachine::multi_crt_did_run_machines() {
// printf("; "); // printf("; ");
// } // }
// printf("\n"); // printf("\n");
std::stable_sort(machines_.begin(), machines_.end(), [] (const auto &lhs, const auto &rhs){ std::stable_sort(machines_.begin(), machines_.end(), [] (const auto &lhs, const auto &rhs){
CRTMachine::Machine *lhs_crt = lhs->crt_machine(); CRTMachine::Machine *lhs_crt = lhs->crt_machine();
CRTMachine::Machine *rhs_crt = rhs->crt_machine(); CRTMachine::Machine *rhs_crt = rhs->crt_machine();

View File

@ -18,6 +18,7 @@
#include "Implementation/MultiKeyboardMachine.hpp" #include "Implementation/MultiKeyboardMachine.hpp"
#include <memory> #include <memory>
#include <mutex>
#include <vector> #include <vector>
namespace Analyser { namespace Analyser {
@ -49,6 +50,7 @@ class MultiMachine: public ::Machine::DynamicMachine, public MultiCRTMachine::De
private: private:
std::vector<std::unique_ptr<DynamicMachine>> machines_; std::vector<std::unique_ptr<DynamicMachine>> machines_;
std::mutex machines_mutex_;
MultiConfigurable configurable_; MultiConfigurable configurable_;
MultiConfigurationTarget configuration_target_; MultiConfigurationTarget configuration_target_;

View File

@ -79,6 +79,7 @@
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
stopOnEveryThreadSanitizerIssue = "YES"
stopOnEveryUBSanitizerIssue = "YES" stopOnEveryUBSanitizerIssue = "YES"
debugServiceExtension = "internal" debugServiceExtension = "internal"
allowLocationSimulation = "NO"> allowLocationSimulation = "NO">