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:
parent
eb39617ad0
commit
e1cab52c84
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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_;
|
||||||
|
@ -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">
|
||||||
|
Loading…
Reference in New Issue
Block a user