mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Merge pull request #1381 from TomHarte/MemoryOrder
Avoid `std::memory_order::memory_order_X` in favour of `std::memory_order_X`.
This commit is contained in:
commit
c67a53e95b
@ -61,7 +61,7 @@ void MultiSpeaker::set_output_volume(float volume) {
|
||||
}
|
||||
|
||||
void MultiSpeaker::speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) {
|
||||
auto delegate = delegate_.load(std::memory_order::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::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 *machine) {
|
||||
std::lock_guard lock_guard(front_speaker_mutex_);
|
||||
front_speaker_ = machine->audio_producer()->get_speaker();
|
||||
}
|
||||
auto delegate = delegate_.load(std::memory_order::memory_order_relaxed);
|
||||
auto delegate = delegate_.load(std::memory_order_relaxed);
|
||||
if(delegate) {
|
||||
delegate->speaker_did_change_input_clock(this);
|
||||
}
|
||||
|
@ -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::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::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::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::memory_order_relaxed);
|
||||
flag.store(true, std::memory_order_relaxed);
|
||||
});
|
||||
|
||||
buffer_pointer_ = (buffer_pointer_ + 1) % BufferCount;
|
||||
|
@ -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::memory_order_relaxed);
|
||||
auto delta_y = delta_y_.load(std::memory_order::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::memory_order_relaxed);
|
||||
const int buttons = button_flags_.load(std::memory_order_relaxed);
|
||||
delta_x_ -= delta_x;
|
||||
delta_y_ -= delta_y;
|
||||
|
||||
|
@ -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::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::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::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::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::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::memory_order_relaxed);
|
||||
pending_stores_[pending_store_read_].store(next_store, std::memory_order_relaxed);
|
||||
pending_store_read_ = (pending_store_read_ + 1) & (StoreBufferSize - 1);
|
||||
}
|
||||
}
|
||||
|
@ -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::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::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;
|
||||
|
||||
|
@ -20,11 +20,11 @@ using namespace Outputs::Display;
|
||||
|
||||
BufferingScanTarget::BufferingScanTarget() {
|
||||
// Ensure proper initialisation of the two atomic pointer sets.
|
||||
read_pointers_.store(write_pointers_, std::memory_order::memory_order_relaxed);
|
||||
submit_pointers_.store(write_pointers_, std::memory_order::memory_order_relaxed);
|
||||
read_pointers_.store(write_pointers_, std::memory_order_relaxed);
|
||||
submit_pointers_.store(write_pointers_, std::memory_order_relaxed);
|
||||
|
||||
// Establish initial state for is_updating_.
|
||||
is_updating_.clear(std::memory_order::memory_order_relaxed);
|
||||
is_updating_.clear(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// MARK: - Producer; pixel data.
|
||||
@ -61,7 +61,7 @@ uint8_t *BufferingScanTarget::begin_data(size_t required_length, size_t required
|
||||
// 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 = TextureAddress(end_x, output_y);
|
||||
const auto read_pointers = read_pointers_.load(std::memory_order::memory_order_relaxed);
|
||||
const auto read_pointers = read_pointers_.load(std::memory_order_relaxed);
|
||||
|
||||
const auto end_distance = TextureSub(end_address, read_pointers.write_area);
|
||||
const auto previous_distance = TextureSub(write_pointers_.write_area, read_pointers.write_area);
|
||||
@ -141,7 +141,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::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_);
|
||||
@ -213,7 +213,7 @@ void BufferingScanTarget::announce(Event event, bool is_visible, const Outputs::
|
||||
#endif
|
||||
|
||||
if(is_visible) {
|
||||
const auto read_pointers = read_pointers_.load(std::memory_order::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_);
|
||||
@ -233,7 +233,7 @@ void BufferingScanTarget::announce(Event event, bool is_visible, const Outputs::
|
||||
} else {
|
||||
// Commit the most recent line only if any scans fell on it and all allocation was successful.
|
||||
if(!allocation_has_failed_ && provided_scans_) {
|
||||
const auto submit_pointers = submit_pointers_.load(std::memory_order::memory_order_relaxed);
|
||||
const auto submit_pointers = submit_pointers_.load(std::memory_order_relaxed);
|
||||
|
||||
// Store metadata.
|
||||
LineMetadata &metadata = line_metadata_buffer_[size_t(write_pointers_.line)];
|
||||
@ -256,12 +256,12 @@ void BufferingScanTarget::announce(Event event, bool is_visible, const Outputs::
|
||||
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.
|
||||
std::atomic_thread_fence(std::memory_order::memory_order_release);
|
||||
submit_pointers_.store(write_pointers_, std::memory_order::memory_order_release);
|
||||
std::atomic_thread_fence(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::memory_order_relaxed);
|
||||
write_pointers_ = submit_pointers_.load(std::memory_order_relaxed);
|
||||
frame_is_complete_ &= !allocation_has_failed_;
|
||||
}
|
||||
|
||||
@ -302,7 +302,7 @@ size_t BufferingScanTarget::write_area_data_size() const {
|
||||
void BufferingScanTarget::set_modals(Modals modals) {
|
||||
perform([=] {
|
||||
modals_ = modals;
|
||||
modals_are_dirty_.store(true, std::memory_order::memory_order_relaxed);
|
||||
modals_are_dirty_.store(true, std::memory_order_relaxed);
|
||||
});
|
||||
}
|
||||
|
||||
@ -312,9 +312,9 @@ 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::memory_order_acquire);
|
||||
const auto read_ahead_pointers = read_ahead_pointers_.load(std::memory_order::memory_order_relaxed);
|
||||
std::atomic_thread_fence(std::memory_order::memory_order_acquire);
|
||||
const auto submit_pointers = submit_pointers_.load(std::memory_order_acquire);
|
||||
const auto read_ahead_pointers = read_ahead_pointers_.load(std::memory_order_relaxed);
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
|
||||
OutputArea area;
|
||||
|
||||
@ -330,7 +330,7 @@ BufferingScanTarget::OutputArea BufferingScanTarget::get_output_area() {
|
||||
area.end.write_area_y = TextureAddressGetY(submit_pointers.write_area);
|
||||
|
||||
// Update the read-ahead pointers.
|
||||
read_ahead_pointers_.store(submit_pointers, std::memory_order::memory_order_relaxed);
|
||||
read_ahead_pointers_.store(submit_pointers, std::memory_order_relaxed);
|
||||
|
||||
#ifndef NDEBUG
|
||||
area.counter = output_area_counter_;
|
||||
@ -347,7 +347,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 = TextureAddress(area.end.write_area_x, area.end.write_area_y);
|
||||
read_pointers_.store(new_read_pointers, std::memory_order::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.
|
||||
@ -374,12 +374,12 @@ void BufferingScanTarget::set_line_buffer(Line *line_buffer, LineMetadata *metad
|
||||
}
|
||||
|
||||
const Outputs::Display::ScanTarget::Modals *BufferingScanTarget::new_modals() {
|
||||
const auto modals_are_dirty = modals_are_dirty_.load(std::memory_order::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::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. They might provide a new pointer and might now.
|
||||
@ -396,5 +396,5 @@ const Outputs::Display::ScanTarget::Modals &BufferingScanTarget::modals() const
|
||||
}
|
||||
|
||||
bool BufferingScanTarget::has_new_modals() const {
|
||||
return modals_are_dirty_.load(std::memory_order::memory_order_relaxed);
|
||||
return modals_are_dirty_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ template <typename ConcreteT, bool is_stereo> class LowpassBase: public Speaker
|
||||
|
||||
protected:
|
||||
bool process(size_t length) {
|
||||
const auto delegate = delegate_.load(std::memory_order::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 @@ template <bool is_stereo> class PushLowpass: public LowpassBase<PushLowpass<is_s
|
||||
|
||||
std::atomic<int> scale_ = 65536;
|
||||
int get_scale() const {
|
||||
return scale_.load(std::memory_order::memory_order_relaxed);
|
||||
return scale_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
const int16_t *buffer_ = nullptr;
|
||||
|
@ -91,7 +91,7 @@ class Speaker {
|
||||
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::memory_order_relaxed), std::memory_order::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 @@ class Speaker {
|
||||
virtual void speaker_did_change_input_clock([[maybe_unused]] Speaker *speaker) {}
|
||||
};
|
||||
virtual void set_delegate(Delegate *delegate) {
|
||||
delegate_.store(delegate, std::memory_order::memory_order_relaxed);
|
||||
delegate_.store(delegate, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
|
||||
@ -139,7 +139,7 @@ class Speaker {
|
||||
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::memory_order_relaxed);
|
||||
const auto delegate = delegate_.load(std::memory_order_relaxed);
|
||||
if(!delegate) return;
|
||||
|
||||
++completed_sample_sets_;
|
||||
|
Loading…
Reference in New Issue
Block a user