mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Ensures thread safety of access to machines array.
This commit is contained in:
parent
eb39617ad0
commit
e1cab52c84
@ -13,25 +13,29 @@
|
||||
|
||||
using namespace Analyser::Dynamic;
|
||||
|
||||
MultiCRTMachine::MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) :
|
||||
machines_(machines), queues_(machines.size()) {}
|
||||
MultiCRTMachine::MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines, std::mutex &machines_mutex) :
|
||||
machines_(machines), machines_mutex_(machines_mutex), queues_(machines.size()) {}
|
||||
|
||||
void MultiCRTMachine::perform_parallel(const std::function<void(::CRTMachine::Machine *)> &function) {
|
||||
// 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.
|
||||
volatile std::size_t outstanding_machines;
|
||||
std::condition_variable condition;
|
||||
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) {
|
||||
queues_[index].enqueue([&mutex, &condition, this, index, function, &outstanding_machines]() {
|
||||
CRTMachine::Machine *crt_machine = machines_[index]->crt_machine();
|
||||
if(crt_machine) function(crt_machine);
|
||||
for(std::size_t index = 0; index < machines_.size(); ++index) {
|
||||
queues_[index].enqueue([&mutex, &condition, this, index, function, &outstanding_machines]() {
|
||||
CRTMachine::Machine *crt_machine = machines_[index]->crt_machine();
|
||||
if(crt_machine) function(crt_machine);
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
outstanding_machines--;
|
||||
condition.notify_all();
|
||||
});
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
outstanding_machines--;
|
||||
condition.notify_all();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
while(true) {
|
||||
@ -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) {
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
for(const auto &machine: machines_) {
|
||||
CRTMachine::Machine *crt_machine = machine->crt_machine();
|
||||
if(crt_machine) function(crt_machine);
|
||||
@ -61,11 +66,13 @@ void MultiCRTMachine::close_output() {
|
||||
}
|
||||
|
||||
Outputs::CRT::CRT *MultiCRTMachine::get_crt() {
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||
return crt_machine ? crt_machine->get_crt() : nullptr;
|
||||
}
|
||||
|
||||
Outputs::Speaker::Speaker *MultiCRTMachine::get_speaker() {
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||
return crt_machine ? crt_machine->get_speaker() : nullptr;
|
||||
}
|
||||
@ -80,11 +87,13 @@ void MultiCRTMachine::run_for(const Cycles cycles) {
|
||||
|
||||
double MultiCRTMachine::get_clock_rate() {
|
||||
// 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();
|
||||
return crt_machine ? crt_machine->get_clock_rate() : 0.0;
|
||||
}
|
||||
|
||||
bool MultiCRTMachine::get_clock_is_unlimited() {
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||
return crt_machine ? crt_machine->get_clock_is_unlimited() : false;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "../../../../Machines/DynamicMachine.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace Analyser {
|
||||
@ -21,7 +22,7 @@ namespace Dynamic {
|
||||
|
||||
class MultiCRTMachine: public ::CRTMachine::Machine, public ::CRTMachine::Machine::Delegate {
|
||||
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 close_output() override;
|
||||
@ -46,6 +47,7 @@ class MultiCRTMachine: public ::CRTMachine::Machine, public ::CRTMachine::Machin
|
||||
|
||||
private:
|
||||
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_;
|
||||
std::mutex &machines_mutex_;
|
||||
std::vector<Concurrency::AsyncTaskQueue> queues_;
|
||||
Delegate *delegate_ = nullptr;
|
||||
|
||||
|
@ -10,19 +10,20 @@
|
||||
|
||||
using namespace Analyser::Dynamic;
|
||||
|
||||
MultiConfigurationTarget::MultiConfigurationTarget(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) :
|
||||
machines_(machines) {}
|
||||
MultiConfigurationTarget::MultiConfigurationTarget(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &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) {
|
||||
}
|
||||
|
||||
bool MultiConfigurationTarget::insert_media(const Analyser::Static::Media &media) {
|
||||
bool inserted = false;
|
||||
for(const auto &machine : machines_) {
|
||||
ConfigurationTarget::Machine *configuration_target = machine->configuration_target();
|
||||
if(configuration_target) {
|
||||
inserted |= configuration_target->insert_media(media);
|
||||
}
|
||||
for(const auto &target : targets_) {
|
||||
inserted |= target->insert_media(media);
|
||||
}
|
||||
return inserted;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
namespace Analyser {
|
||||
namespace Dynamic {
|
||||
|
||||
struct MultiConfigurationTarget: public ::ConfigurationTarget::Machine {
|
||||
struct MultiConfigurationTarget: public ConfigurationTarget::Machine {
|
||||
public:
|
||||
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;
|
||||
|
||||
private:
|
||||
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_;
|
||||
std::vector<ConfigurationTarget::Machine *> targets_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ MultiMachine::MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machin
|
||||
machines_(std::move(machines)),
|
||||
configurable_(machines_),
|
||||
configuration_target_(machines_),
|
||||
crt_machine_(machines_),
|
||||
crt_machine_(machines_, machines_mutex_),
|
||||
joystick_machine_(machines),
|
||||
keyboard_machine_(machines_) {
|
||||
crt_machine_.set_delegate(this);
|
||||
@ -41,6 +41,7 @@ Configurable::Device *MultiMachine::configurable_device() {
|
||||
}
|
||||
|
||||
void MultiMachine::multi_crt_did_run_machines() {
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
DynamicMachine *front = machines_.front().get();
|
||||
// for(const auto &machine: machines_) {
|
||||
// CRTMachine::Machine *crt = machine->crt_machine();
|
||||
@ -49,6 +50,7 @@ void MultiMachine::multi_crt_did_run_machines() {
|
||||
// printf("; ");
|
||||
// }
|
||||
// printf("\n");
|
||||
|
||||
std::stable_sort(machines_.begin(), machines_.end(), [] (const auto &lhs, const auto &rhs){
|
||||
CRTMachine::Machine *lhs_crt = lhs->crt_machine();
|
||||
CRTMachine::Machine *rhs_crt = rhs->crt_machine();
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "Implementation/MultiKeyboardMachine.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace Analyser {
|
||||
@ -49,6 +50,7 @@ class MultiMachine: public ::Machine::DynamicMachine, public MultiCRTMachine::De
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<DynamicMachine>> machines_;
|
||||
std::mutex machines_mutex_;
|
||||
|
||||
MultiConfigurable configurable_;
|
||||
MultiConfigurationTarget configuration_target_;
|
||||
|
@ -79,6 +79,7 @@
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
stopOnEveryThreadSanitizerIssue = "YES"
|
||||
stopOnEveryUBSanitizerIssue = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "NO">
|
||||
|
Loading…
Reference in New Issue
Block a user