Merge pull request #1894 from TomHarte/NoMoreConditionVariable

Use std::atomic_flag::wait.
This commit is contained in:
Thomas Harte authored and GitHub committed 2026-10-07 07:56:07 -04:00
commit bef417c0dc
18 files changed
+88 -98

No files matched your search

@@ -8,8 +8,7 @@
#include "MultiProducer.hpp"
#include <condition_variable>
#include <mutex>
#include <atomic>
using namespace Analyser::Dynamic;
@@ -19,28 +18,23 @@ template <typename MachineType>
void MultiInterface<MachineType>::perform_parallel(const std::function<void(MachineType *)> &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.
std::size_t outstanding_machines;
std::condition_variable condition;
std::mutex mutex;
std::atomic<int> outstanding_machines = int(machines_.size());
std::atomic_flag finished{};
{
std::lock_guard machines_lock(machines_mutex_);
std::lock_guard lock(mutex);
outstanding_machines = machines_.size();
for(std::size_t index = 0; index < machines_.size(); ++index) {
const auto machine = ::Machine::get<MachineType>(*machines_[index].get());
queues_[index].enqueue([&mutex, &condition, machine, function, &outstanding_machines]() {
queues_[index].enqueue([&finished, machine, function, &outstanding_machines]() {
if(machine) function(machine);
std::lock_guard lock(mutex);
--outstanding_machines;
condition.notify_all();
if(outstanding_machines.fetch_sub(1, std::memory_order::relaxed) == 1) {
finished.test_and_set(std::memory_order::release);
finished.notify_one();
}
});
}
}
std::unique_lock lock(mutex);
condition.wait(lock, [&outstanding_machines] { return !outstanding_machines; });
finished.wait(false, std::memory_order::acquire);
}
template <typename MachineType>
@@ -61,7 +61,7 @@ void MultiSpeaker::set_output_volume(const float volume) {
}
void MultiSpeaker::speaker_did_complete_samples(Speaker &speaker, const std::vector<int16_t> &buffer) {
auto delegate = delegate_.load(std::memory_order_relaxed);
auto delegate = delegate_.load(std::memory_order::relaxed);
if(!delegate) return;
{
std::lock_guard lock_guard(front_speaker_mutex_);
@@ -71,7 +71,7 @@ void MultiSpeaker::speaker_did_complete_samples(Speaker &speaker, const std::vec
}
void MultiSpeaker::speaker_did_change_input_clock(Speaker &speaker) {
auto delegate = delegate_.load(std::memory_order_relaxed);
auto delegate = delegate_.load(std::memory_order::relaxed);
if(!delegate) return;
{
std::lock_guard lock_guard(front_speaker_mutex_);
@@ -85,7 +85,7 @@ void MultiSpeaker::set_new_front_machine(::Machine::DynamicMachine *const machin
std::lock_guard lock_guard(front_speaker_mutex_);
front_speaker_ = machine->audio_producer()->get_speaker();
}
auto delegate = delegate_.load(std::memory_order_relaxed);
auto delegate = delegate_.load(std::memory_order::relaxed);
if(delegate) {
delegate->speaker_did_change_input_clock(*this);
}
+2 -2
View File
@@ -25,7 +25,7 @@ void uPD7002::run_for(const HalfCycles count) {
if(count >= conversion_time_remaining_) {
conversion_time_remaining_ = HalfCycles(0);
result_ = uint16_t(
inputs_[channel_].load(std::memory_order_relaxed) * 65535.0f) & (high_precision_ ? 0xfff0 : 0xff00
inputs_[channel_].load(std::memory_order::relaxed) * 65535.0f) & (high_precision_ ? 0xfff0 : 0xff00
);
set_interrupt(true);
return;
@@ -83,5 +83,5 @@ void uPD7002::set_interrupt(const bool value) {
}
void uPD7002::set_input(const int channel, const float value) {
inputs_[channel].store(value, std::memory_order_relaxed);
inputs_[channel].store(value, std::memory_order::relaxed);
}
+7 -11
View File
@@ -147,22 +147,18 @@ public:
/// Schedules any remaining unscheduled work, then blocks synchronously
/// until all scheduled work has been performed.
void lock_flush() {
std::mutex flush_mutex;
std::condition_variable flush_condition;
bool has_run = false;
std::unique_lock lock(flush_mutex);
std::atomic_flag flushed = false;
enqueue([&flush_mutex, &flush_condition, &has_run] () {
std::unique_lock inner_lock(flush_mutex);
has_run = true;
flush_condition.notify_one();
enqueue([&flushed] () {
flushed.test_and_set(std::memory_order::release);
flushed.notify_one();
});
if constexpr (!perform_automatically) {
perform();
}
flush_condition.wait(lock, [&has_run] { return has_run; });
flushed.wait(false, std::memory_order::acquire);
}
/// Schedules any remaining unscheduled work, then spins
@@ -195,11 +191,11 @@ private:
ActionVector actions;
// Continue until told to quit.
while(!should_quit_.test(std::memory_order_relaxed)) {
while(!should_quit_.test(std::memory_order::relaxed)) {
// Wait for new actions to be signalled, and grab them.
std::unique_lock lock(condition_mutex_);
condition_.wait(lock, [&] {
return !actions_.empty() || should_quit_.test(std::memory_order_relaxed);
return !actions_.empty() || should_quit_.test(std::memory_order::relaxed);
});
std::swap(actions, actions_);
lock.unlock();
+2 -2
View File
@@ -36,9 +36,9 @@ public:
private:
static constexpr auto LockMemoryOrder =
type == Barrier::Relaxed ? std::memory_order_relaxed : std::memory_order_acquire;
type == Barrier::Relaxed ? std::memory_order::relaxed : std::memory_order::acquire;
static constexpr auto UnlockMemoryOrder =
type == Barrier::Relaxed ? std::memory_order_relaxed : std::memory_order_release;
type == Barrier::Relaxed ? std::memory_order::relaxed : std::memory_order::release;
// Note to self: this is guaranteed to construct in a clear state since C++20.
std::atomic_flag flag_;
+4 -4
View File
@@ -20,7 +20,7 @@ Audio::Audio(Chipset &chipset, uint16_t *ram, size_t word_size, float output_rat
// Mark all buffers as available.
for(auto &flag: buffer_available_) {
flag.store(true, std::memory_order_relaxed);
flag.store(true, std::memory_order::relaxed);
}
speaker_.set_input_rate(output_rate);
@@ -130,7 +130,7 @@ void Audio::output() {
// Spin until the next buffer is available if just entering it for the first time.
// Contention here should be essentially non-existent.
if(!sample_pointer_) {
while(!buffer_available_[buffer_pointer_].load(std::memory_order_relaxed));
while(!buffer_available_[buffer_pointer_].load(std::memory_order::relaxed));
}
// Left.
@@ -155,10 +155,10 @@ void Audio::output() {
const auto &buffer = buffer_[buffer_pointer_];
auto &flag = buffer_available_[buffer_pointer_];
flag.store(false, std::memory_order_release);
flag.store(false, std::memory_order::release);
queue_.enqueue([this, &buffer, &flag] {
speaker_.push(buffer.data(), buffer.size() >> 1);
flag.store(true, std::memory_order_relaxed);
flag.store(true, std::memory_order::relaxed);
});
buffer_pointer_ = (buffer_pointer_ + 1) % BufferCount;
+3 -3
View File
@@ -25,15 +25,15 @@ void Mouse::perform_command(const Command &command) {
// There's some small chance of creating negative feedback here — taking too much off delta_x_ or delta_y_
// due to a change in the underlying value between the load and the arithmetic. But if that occurs it means
// the user moved the mouse again in the interim, so it'll just play out as very slight latency.
auto delta_x = delta_x_.load(std::memory_order_relaxed);
auto delta_y = delta_y_.load(std::memory_order_relaxed);
auto delta_x = delta_x_.load(std::memory_order::relaxed);
auto delta_y = delta_y_.load(std::memory_order::relaxed);
if(abs(delta_x) > max_delta || abs(delta_y) > max_delta) {
int max = std::max(abs(delta_x), abs(delta_y));
delta_x = delta_x * max_delta / max;
delta_y = delta_y * max_delta / max;
}
const int buttons = button_flags_.load(std::memory_order_relaxed);
const int buttons = button_flags_.load(std::memory_order::relaxed);
delta_x_ -= delta_x;
delta_y_ -= delta_y;
+6 -6
View File
@@ -35,7 +35,7 @@ void GLU::set_data(uint8_t data) {
write.address = address_;
write.value = data;
write.time = pending_store_write_time_;
pending_stores_[pending_store_write_].store(write, std::memory_order_release);
pending_stores_[pending_store_write_].store(write, std::memory_order::release);
pending_store_write_ = (pending_store_write_ + 1) % (StoreBufferSize - 1);
} else {
@@ -174,15 +174,15 @@ template void GLU::apply_samples<Outputs::Speaker::Action::Ignore>(std::size_t,
// skip_audio(remote_, number_of_samples);
//
// // Apply any pending stores.
// std::atomic_thread_fence(std::memory_order_acquire);
// std::atomic_thread_fence(std::memory_order::acquire);
// const uint32_t final_time = pending_store_read_time_ + uint32_t(number_of_samples);
// while(true) {
// auto next_store = pending_stores_[pending_store_read_].load(std::memory_order_acquire);
// auto next_store = pending_stores_[pending_store_read_].load(std::memory_order::acquire);
// if(!next_store.enabled) break;
// if(next_store.time >= final_time) break;
// remote_.ram_[next_store.address] = next_store.value;
// next_store.enabled = false;
// pending_stores_[pending_store_read_].store(next_store, std::memory_order_relaxed);
// pending_stores_[pending_store_read_].store(next_store, std::memory_order::relaxed);
//
// pending_store_read_ = (pending_store_read_ + 1) & (StoreBufferSize - 1);
// }
@@ -263,7 +263,7 @@ void GLU::skip_audio(EnsoniqState &state, size_t number_of_samples) {
template <Outputs::Speaker::Action action>
void GLU::generate_audio(size_t number_of_samples, Outputs::Speaker::MonoSample *target) {
auto next_store = pending_stores_[pending_store_read_].load(std::memory_order_acquire);
auto next_store = pending_stores_[pending_store_read_].load(std::memory_order::acquire);
uint8_t next_amplitude = 255;
for(size_t sample = 0; sample < number_of_samples; sample++) {
@@ -344,7 +344,7 @@ void GLU::generate_audio(size_t number_of_samples, Outputs::Speaker::MonoSample
if(next_store.time != pending_store_read_time_) continue;
remote_.ram_[next_store.address] = next_store.value;
next_store.enabled = false;
pending_stores_[pending_store_read_].store(next_store, std::memory_order_relaxed);
pending_stores_[pending_store_read_].store(next_store, std::memory_order::relaxed);
pending_store_read_ = (pending_store_read_ + 1) & (StoreBufferSize - 1);
}
}
+2 -2
View File
@@ -27,7 +27,7 @@ Audio::Audio(Concurrency::AsyncTaskQueue<false> &task_queue) : task_queue_(task_
void Audio::post_sample(uint8_t sample) {
// Store sample directly indexed by current write pointer; this ensures that collected samples
// directly map to volume and enabled/disabled states.
sample_queue_.buffer[sample_queue_.write_pointer].store(sample, std::memory_order_relaxed);
sample_queue_.buffer[sample_queue_.write_pointer].store(sample, std::memory_order::relaxed);
sample_queue_.write_pointer = (sample_queue_.write_pointer + 1) % sample_queue_.buffer.size();
}
@@ -82,7 +82,7 @@ void Audio::apply_samples(std::size_t number_of_samples, Outputs::Speaker::MonoS
const auto cycles_left_in_sample = std::min(number_of_samples, sample_length - subcycle_offset_);
// Determine the output level, and output that many samples.
const int16_t output_level = volume_multiplier_ * (int16_t(sample_queue_.buffer[sample_queue_.read_pointer].load(std::memory_order_relaxed)) - 128);
const int16_t output_level = volume_multiplier_ * (int16_t(sample_queue_.buffer[sample_queue_.read_pointer].load(std::memory_order::relaxed)) - 128);
Outputs::Speaker::fill<action>(target, target + cycles_left_in_sample, output_level);
target += cycles_left_in_sample;
+2 -2
View File
@@ -524,7 +524,7 @@ public:
value = result;
// Consider applying the fast tape hack.
if(use_fast_tape_hack_.load(std::memory_order_relaxed) && operation == CPU::MOS6502Mk2::BusOperation::ReadOpcode) {
if(use_fast_tape_hack_.load(std::memory_order::relaxed) && operation == CPU::MOS6502Mk2::BusOperation::ReadOpcode) {
if(address == 0xf7b2) {
// Address 0xf7b2 contains a JSR to 0xf8c0 ('RDTPBLKS') that will fill the tape buffer with the
// next header. Skip that via a three-byte NOP and fill in the next header programmatically.
@@ -796,7 +796,7 @@ private:
void set_use_fast_tape() {
use_fast_tape_hack_.store(
!tape_is_sleeping_ && allow_fast_tape_hack_ && tape_->has_tape(),
std::memory_order_relaxed
std::memory_order::relaxed
);
}
+4 -4
View File
@@ -62,11 +62,11 @@ public:
void did_set_input(const Input &digital_input, bool is_active) final {
const auto apply_kempston = [&](uint8_t mask) {
if(is_active) write_kempston_ |= mask; else write_kempston_ &= ~mask;
kempston_.store(write_kempston_, std::memory_order_relaxed);
kempston_.store(write_kempston_, std::memory_order::relaxed);
};
const auto apply_sinclair = [&](uint16_t mask) {
if(is_active) write_sinclair_ &= ~mask; else write_sinclair_ |= mask;
sinclair_.store(write_sinclair_, std::memory_order_relaxed);
sinclair_.store(write_sinclair_, std::memory_order::relaxed);
};
switch(digital_input.type) {
@@ -98,13 +98,13 @@ public:
/// @returns The value that a Kempston joystick interface would report if this joystick
/// were plugged into it.
uint8_t get_kempston() {
return kempston_.load(std::memory_order_relaxed);
return kempston_.load(std::memory_order::relaxed);
}
/// @returns The value that a Sinclair interface would report if this joystick
/// were plugged into it via @c port (which should be either 0 or 1, for ports 1 or 2).
uint8_t get_sinclair(const int port) {
return uint8_t(sinclair_.load(std::memory_order_relaxed) >> (port * 8));
return uint8_t(sinclair_.load(std::memory_order::relaxed) >> (port * 8));
}
private:
@@ -197,12 +197,12 @@ struct ActivityObserver: public Activity::Observer {
_machine->scan_producer()->set_scan_target(_view.scanTarget.scanTarget);
_ownedUpdater = std::make_unique<Updater>();
std::atomic_thread_fence(std::memory_order_release);
std::atomic_thread_fence(std::memory_order::release);
_ownedUpdater->performer.machine = _machine.get();
if(_ownedUpdater->performer.machine) {
_ownedUpdater->start();
}
_updater.store(_ownedUpdater.get(), std::memory_order_relaxed);
_updater.store(_ownedUpdater.get(), std::memory_order::relaxed);
_leds = [[NSMutableArray alloc] init];
Activity::Source *const activity_source = _machine->activity_source();
@@ -384,7 +384,7 @@ struct ActivityObserver: public Activity::Observer {
}
- (void)applyMedia:(const Analyser::Static::Media &)media {
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return;
__weak CSMachine *weakSelf = self;
@@ -565,7 +565,7 @@ struct ActivityObserver: public Activity::Observer {
}
- (void)applyInputEvent:(dispatch_block_t)event {
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return;
updater->enqueue([event] {
@@ -799,7 +799,7 @@ struct ActivityObserver: public Activity::Observer {
- (void)audioQueueIsRunningDry:(nonnull CSAudioQueue *)audioQueue {
__weak CSMachine *weakSelf = self;
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return;
updater->enqueue([weakSelf, updater] {
@@ -817,7 +817,7 @@ struct ActivityObserver: public Activity::Observer {
__weak CSMachine *weakSelf = self;
const auto refreshPeriod = view.refreshPeriod;
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return;
updater->enqueue([weakSelf, refreshPeriod, updater] {
@@ -870,7 +870,7 @@ struct ActivityObserver: public Activity::Observer {
}
- (void)stop {
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return;
updater->stop();
}
@@ -880,7 +880,7 @@ struct ActivityObserver: public Activity::Observer {
}
- (void)hardReset {
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return;
__weak CSMachine *weakSelf = self;
@@ -894,13 +894,13 @@ struct ActivityObserver: public Activity::Observer {
}
- (BOOL)canHardReset {
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return NO;
return updater->performer.machine->hard_resettable() != nullptr;
}
- (void)softReset {
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return;
__weak CSMachine *weakSelf = self;
@@ -914,7 +914,7 @@ struct ActivityObserver: public Activity::Observer {
}
- (BOOL)canSoftReset {
const auto updater = _updater.load(std::memory_order_relaxed);
const auto updater = _updater.load(std::memory_order::relaxed);
if(!updater) return NO;
return updater->performer.machine->soft_resettable() != nullptr;
}
+1 -1
View File
@@ -459,7 +459,7 @@ Outputs::Display::ScanTarget::Scan::EndPoint CRT::end_point(const uint16_t data_
// Clamp the available range on endpoints. These will almost always be within range, but may go
// out during times of resync.
.x = uint16_t(std::min(horizontal_flywheel_.current_output_position(), 65535)),
.y = preferences_.force_horizontal_scans.load(std::memory_order_relaxed) ?
.y = preferences_.force_horizontal_scans.load(std::memory_order::relaxed) ?
start_of_line_y_ : current_vertical_flywheel(),
.data_offset = data_offset,
+1 -1
View File
@@ -468,7 +468,7 @@ private:
void set(const Preferences &preferences) override {
force_horizontal_scans.store(
preferences.force_horizontal_scans.value_or(DefaultForceHorizontalScans),
std::memory_order_relaxed
std::memory_order::relaxed
);
}
} preferences_;
+2 -2
View File
@@ -611,7 +611,7 @@ void ScanTarget::output_scans(const OutputArea &area) {
}
void ScanTarget::draw(const int output_width, const int output_height) {
while(is_drawing_to_output_.test_and_set(std::memory_order_acquire));
while(is_drawing_to_output_.test_and_set(std::memory_order::acquire));
test_gl([&]{ glBindFramebuffer(GL_FRAMEBUFFER, target_framebuffer_); });
test_gl([&]{ glViewport(0, 0, (GLsizei)output_width, (GLsizei)output_height); });
@@ -637,5 +637,5 @@ void ScanTarget::draw(const int output_width, const int output_height) {
was_interlacing_ = is_interlacing_;
}
is_drawing_to_output_.clear(std::memory_order_release);
is_drawing_to_output_.clear(std::memory_order::release);
}
+24 -24
View File
@@ -30,8 +30,8 @@ using namespace Outputs::Display;
BufferingScanTarget::BufferingScanTarget() {
// Ensure proper initialisation of the two atomic pointer sets.
read_pointers_.store(write_pointers_, std::memory_order_relaxed);
submit_pointers_.store(write_pointers_, std::memory_order_relaxed);
read_pointers_.store(write_pointers_, std::memory_order::relaxed);
submit_pointers_.store(write_pointers_, std::memory_order::relaxed);
}
// MARK: - Producer; pixel data.
@@ -68,7 +68,7 @@ uint8_t *BufferingScanTarget::begin_data(const size_t required_length, const siz
// Check whether that steps over the read pointer; if so then the final address will be closer
// to the write pointer than the old.
const auto end_address = texture_address(end_x, output_y);
const auto read_pointers = read_pointers_.load(std::memory_order_relaxed);
const auto read_pointers = read_pointers_.load(std::memory_order::relaxed);
const auto end_distance = texture_address_sub(end_address, read_pointers.write_area);
const auto previous_distance = texture_address_sub(write_pointers_.write_area, read_pointers.write_area);
@@ -154,7 +154,7 @@ Outputs::Display::ScanTarget::Scan *BufferingScanTarget::begin_scan() {
}
const auto result = &scan_buffer_[write_pointers_.scan];
const auto read_pointers = read_pointers_.load(std::memory_order_relaxed);
const auto read_pointers = read_pointers_.load(std::memory_order::relaxed);
// Advance the pointer.
const auto next_write_pointer = decltype(write_pointers_.scan)((write_pointers_.scan + 1) % scan_buffer_size_);
@@ -221,8 +221,8 @@ void BufferingScanTarget::announce(
previous_frame_was_complete_ = frame_is_complete_;
frame_is_complete_ = true;
auto write = frame_write_.load(std::memory_order_relaxed);
const auto submit_pointers = submit_pointers_.load(std::memory_order_relaxed);
auto write = frame_write_.load(std::memory_order::relaxed);
const auto submit_pointers = submit_pointers_.load(std::memory_order::relaxed);
auto &frame = frames_[size_t(write)];
frame.first_line = submit_pointers.line;
@@ -233,12 +233,12 @@ void BufferingScanTarget::announce(
field_index_ ^= 1;
++write;
frame_write_.store(write, std::memory_order_release);
frame_write_.store(write, std::memory_order::release);
auto read = frame_read_.load(std::memory_order_relaxed);
auto read = frame_read_.load(std::memory_order::relaxed);
if(read == write) {
++read;
frame_read_.store(read, std::memory_order_relaxed);
frame_read_.store(read, std::memory_order::relaxed);
}
// Look for an even-odd pattern in start-of-frame line placement as an indication that
@@ -275,7 +275,7 @@ void BufferingScanTarget::announce(
#endif
if(is_visible) {
const auto read_pointers = read_pointers_.load(std::memory_order_relaxed);
const auto read_pointers = read_pointers_.load(std::memory_order::relaxed);
// Attempt to allocate a new line, noting allocation success or failure.
const auto next_line = uint16_t((write_pointers_.line + 1) % line_buffer_size_);
@@ -305,11 +305,11 @@ void BufferingScanTarget::announce(
write_pointers_.line = uint16_t((write_pointers_.line + 1) % line_buffer_size_);
// Update the submit pointers with all lines, scans and data written during this line.
submit_pointers_.store(write_pointers_, std::memory_order_release);
submit_pointers_.store(write_pointers_, std::memory_order::release);
} else {
// Something failed, or there was nothing on the line anyway, so reset all pointers to where they
// were before this line. Mark frame as incomplete if this was an allocation failure.
write_pointers_ = submit_pointers_.load(std::memory_order_relaxed);
write_pointers_ = submit_pointers_.load(std::memory_order::relaxed);
frame_is_complete_ &= !allocation_has_failed_;
}
}
@@ -347,7 +347,7 @@ size_t BufferingScanTarget::write_area_data_size() const {
void BufferingScanTarget::set_modals(const Modals modals) {
perform([&] {
modals_ = modals;
modals_are_dirty_.store(true, std::memory_order_relaxed);
modals_are_dirty_.store(true, std::memory_order::relaxed);
});
}
@@ -361,10 +361,10 @@ BufferingScanTarget::OutputArea BufferingScanTarget::get_output_area() {
// The area to draw is that between the read pointers, representing wherever reading
// last stopped, and the submit pointers, representing all the new data that has been
// cleared for submission.
const auto submit_pointers = submit_pointers_.load(std::memory_order_acquire);
const auto read_ahead_pointers = read_ahead_pointers_.load(std::memory_order_relaxed);
const auto frame_read = frame_read_.load(std::memory_order_relaxed);
const auto frame_write = frame_write_.load(std::memory_order_relaxed);
const auto submit_pointers = submit_pointers_.load(std::memory_order::acquire);
const auto read_ahead_pointers = read_ahead_pointers_.load(std::memory_order::relaxed);
const auto frame_read = frame_read_.load(std::memory_order::relaxed);
const auto frame_write = frame_write_.load(std::memory_order::relaxed);
OutputArea area;
@@ -383,8 +383,8 @@ BufferingScanTarget::OutputArea BufferingScanTarget::get_output_area() {
area.end.write_area_y = texture_address_get_y(submit_pointers.write_area);
// Update the read-ahead pointers.
read_ahead_pointers_.store(submit_pointers, std::memory_order_relaxed);
frame_read_.store(frame_write, std::memory_order_relaxed);
read_ahead_pointers_.store(submit_pointers, std::memory_order::relaxed);
frame_read_.store(frame_write, std::memory_order::relaxed);
#ifndef NDEBUG
area.counter = output_area_counter_;
@@ -399,7 +399,7 @@ void BufferingScanTarget::complete_output_area(const OutputArea &area) {
new_read_pointers.line = uint16_t(area.end.line);
new_read_pointers.scan = uint16_t(area.end.scan);
new_read_pointers.write_area = texture_address(uint16_t(area.end.write_area_x), uint16_t(area.end.write_area_y));
read_pointers_.store(new_read_pointers, std::memory_order_relaxed);
read_pointers_.store(new_read_pointers, std::memory_order::relaxed);
#ifndef NDEBUG
// This will fire if the caller is announcing completed output areas out of order.
@@ -422,17 +422,17 @@ void BufferingScanTarget::set_line_buffer(
}
const Outputs::Display::ScanTarget::Modals *BufferingScanTarget::new_modals() {
const auto modals_are_dirty = modals_are_dirty_.load(std::memory_order_relaxed);
const auto modals_are_dirty = modals_are_dirty_.load(std::memory_order::relaxed);
if(!modals_are_dirty) {
return nullptr;
}
modals_are_dirty_.store(false, std::memory_order_relaxed);
modals_are_dirty_.store(false, std::memory_order::relaxed);
// MAJOR SHARP EDGE HERE: assume that because the new_modals have been fetched then the caller will
// now ensure their texture buffer is appropriate and set the data size implied by the data type.
std::lock_guard lock_guard(producer_lock_);
std::atomic_thread_fence(std::memory_order_acquire);
std::atomic_thread_fence(std::memory_order::acquire);
data_type_size_ = Outputs::Display::size_for_data_type(modals_.input_data_type);
assert((data_type_size_ == 1) || (data_type_size_ == 2) || (data_type_size_ == 4));
@@ -444,5 +444,5 @@ const Outputs::Display::ScanTarget::Modals &BufferingScanTarget::modals() const
}
bool BufferingScanTarget::has_new_modals() const {
return modals_are_dirty_.load(std::memory_order_relaxed);
return modals_are_dirty_.load(std::memory_order::relaxed);
}
@@ -239,7 +239,7 @@ private:
protected:
bool process(size_t length) {
const auto delegate = delegate_.load(std::memory_order_relaxed);
const auto delegate = delegate_.load(std::memory_order::relaxed);
if(!delegate) return false;
const int scale = static_cast<ConcreteT *>(this)->get_scale();
@@ -301,7 +301,7 @@ private:
std::atomic<int> scale_ = 65536;
int get_scale() const {
return scale_.load(std::memory_order_relaxed);
return scale_.load(std::memory_order::relaxed);
}
const int16_t *buffer_ = nullptr;
+3 -3
View File
@@ -91,7 +91,7 @@ public:
void copy_output_rate(const Speaker &rhs) {
output_cycles_per_second_ = rhs.output_cycles_per_second_;
output_buffer_size_ = rhs.output_buffer_size_;
stereo_output_.store(rhs.stereo_output_.load(std::memory_order_relaxed), std::memory_order_relaxed);
stereo_output_.store(rhs.stereo_output_.load(std::memory_order::relaxed), std::memory_order::relaxed);
compute_output_rate();
}
@@ -129,7 +129,7 @@ public:
virtual void speaker_did_change_input_clock(Speaker &) {}
};
virtual void set_delegate(Delegate *delegate) {
delegate_.store(delegate, std::memory_order_relaxed);
delegate_.store(delegate, std::memory_order::relaxed);
}
@@ -139,7 +139,7 @@ public:
protected:
void did_complete_samples(Speaker *, const std::vector<int16_t> &buffer, bool is_stereo) {
// Test the delegate for existence again, as it may have changed.
const auto delegate = delegate_.load(std::memory_order_relaxed);
const auto delegate = delegate_.load(std::memory_order::relaxed);
if(!delegate) return;
++completed_sample_sets_;