mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
std::atomic - 2nd batch of changes to convert from glib to std::atomic
This commit is contained in:
parent
c304edd253
commit
a486fba3e9
30 changed files with 179 additions and 233 deletions
|
|
@ -118,7 +118,7 @@ class LIBARDOUR_API AudioEngine : public PortManager, public SessionHandlePtr
|
||||||
bool is_realtime() const;
|
bool is_realtime() const;
|
||||||
|
|
||||||
// for the user which hold state_lock to check if reset operation is pending
|
// for the user which hold state_lock to check if reset operation is pending
|
||||||
bool is_reset_requested() const { return g_atomic_int_get (const_cast<std::atomic<int>*> (&_hw_reset_request_count)); }
|
bool is_reset_requested() const { return _hw_reset_request_count.load(); }
|
||||||
|
|
||||||
int set_device_name (const std::string&);
|
int set_device_name (const std::string&);
|
||||||
int set_sample_rate (float);
|
int set_sample_rate (float);
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ public:
|
||||||
void start_touch (timepos_t const & when);
|
void start_touch (timepos_t const & when);
|
||||||
void stop_touch (timepos_t const & when);
|
void stop_touch (timepos_t const & when);
|
||||||
|
|
||||||
bool touching () const { return g_atomic_int_get (const_cast<std::atomic<int>*>(&_touching)) != 0; }
|
bool touching () const { return _touching.load() != 0; }
|
||||||
bool writing () const { return _state == Write; }
|
bool writing () const { return _state == Write; }
|
||||||
bool touch_enabled () const { return _state & (Touch | Latch); }
|
bool touch_enabled () const { return _state & (Touch | Latch); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#define _ardour_circular_buffer_h_
|
#define _ardour_circular_buffer_h_
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "pbd/ringbuffer.h"
|
#include "pbd/ringbuffer.h"
|
||||||
|
|
||||||
|
|
@ -36,11 +37,11 @@ namespace ARDOUR {
|
||||||
class LIBARDOUR_API CircularSampleBuffer
|
class LIBARDOUR_API CircularSampleBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CircularSampleBuffer (samplecnt_t size);
|
CircularSampleBuffer (size_t size);
|
||||||
|
|
||||||
void silence (samplecnt_t);
|
void silence (size_t);
|
||||||
void write (Sample const*, samplecnt_t);
|
void write (Sample const*, size_t);
|
||||||
bool read (Sample& s_min, Sample& s_max, samplecnt_t n_samples);
|
bool read (Sample& s_min, Sample& s_max, size_t n_samples);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PBD::RingBuffer<Sample> _rb;
|
PBD::RingBuffer<Sample> _rb;
|
||||||
|
|
@ -59,7 +60,7 @@ public:
|
||||||
|
|
||||||
typedef std::vector<Event> EventList;
|
typedef std::vector<Event> EventList;
|
||||||
|
|
||||||
CircularEventBuffer (samplecnt_t size);
|
CircularEventBuffer (size_t size);
|
||||||
~CircularEventBuffer ();
|
~CircularEventBuffer ();
|
||||||
|
|
||||||
void reset ();
|
void reset ();
|
||||||
|
|
@ -70,11 +71,11 @@ private:
|
||||||
CircularEventBuffer (CircularEventBuffer const&);
|
CircularEventBuffer (CircularEventBuffer const&);
|
||||||
|
|
||||||
Event* _buf;
|
Event* _buf;
|
||||||
guint _size;
|
size_t _size;
|
||||||
guint _size_mask;
|
size_t _size_mask;
|
||||||
|
|
||||||
std::atomic<int> _idx;
|
std::atomic<size_t> _idx;
|
||||||
std::atomic<int> _ack;
|
std::atomic<size_t> _ack;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,8 @@ public:
|
||||||
|
|
||||||
std::list<std::shared_ptr<Source> >& last_capture_sources () { return _last_capture_sources; }
|
std::list<std::shared_ptr<Source> >& last_capture_sources () { return _last_capture_sources; }
|
||||||
|
|
||||||
bool record_enabled () const { return g_atomic_int_get (const_cast<std::atomic<int>*>(&_record_enabled)); }
|
bool record_enabled () const { return _record_enabled.load(); }
|
||||||
bool record_safe () const { return g_atomic_int_get (const_cast<std::atomic<int>*>(&_record_safe)); }
|
bool record_safe () const { return _record_safe.load(); }
|
||||||
|
|
||||||
void set_record_enabled (bool yn);
|
void set_record_enabled (bool yn);
|
||||||
void set_record_safe (bool yn);
|
void set_record_safe (bool yn);
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,9 @@
|
||||||
#ifndef _dsp_filter_h_
|
#ifndef _dsp_filter_h_
|
||||||
#define _dsp_filter_h_
|
#define _dsp_filter_h_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <atomic>
|
||||||
#include <string.h>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glibmm.h>
|
#include <glibmm.h>
|
||||||
|
|
@ -112,7 +113,8 @@ namespace ARDOUR { namespace DSP {
|
||||||
* @param val value to set
|
* @param val value to set
|
||||||
*/
|
*/
|
||||||
void atomic_set_int (size_t off, int32_t val) {
|
void atomic_set_int (size_t off, int32_t val) {
|
||||||
g_atomic_int_set (&(((int32_t*)_data)[off]), val);
|
((int32_t*)_data)[off] = val;
|
||||||
|
std::atomic_thread_fence (std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** atomically read integer at offset
|
/** atomically read integer at offset
|
||||||
|
|
@ -125,7 +127,8 @@ namespace ARDOUR { namespace DSP {
|
||||||
* @returns value at offset
|
* @returns value at offset
|
||||||
*/
|
*/
|
||||||
int32_t atomic_get_int (size_t off) {
|
int32_t atomic_get_int (size_t off) {
|
||||||
return g_atomic_int_get (&(((int32_t*)_data)[off]));
|
std::atomic_thread_fence (std::memory_order_acquire);
|
||||||
|
return (((int32_t*)_data)[off]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -107,25 +107,25 @@ private:
|
||||||
void helper_thread ();
|
void helper_thread ();
|
||||||
|
|
||||||
PBD::MPMCQueue<ProcessNode*> _trigger_queue; ///< nodes that can be processed
|
PBD::MPMCQueue<ProcessNode*> _trigger_queue; ///< nodes that can be processed
|
||||||
std::atomic<unsigned int> _trigger_queue_size; ///< number of entries in trigger-queue
|
std::atomic<uint32_t> _trigger_queue_size; ///< number of entries in trigger-queue
|
||||||
|
|
||||||
/** Start worker threads */
|
/** Start worker threads */
|
||||||
PBD::Semaphore _execution_sem;
|
PBD::Semaphore _execution_sem;
|
||||||
|
|
||||||
/** The number of processing threads that are asleep */
|
/** The number of processing threads that are asleep */
|
||||||
std::atomic<unsigned int> _idle_thread_cnt;
|
std::atomic<uint32_t> _idle_thread_cnt;
|
||||||
|
|
||||||
/** Signalled to start a run of the graph for a process callback */
|
/** Signalled to start a run of the graph for a process callback */
|
||||||
PBD::Semaphore _callback_start_sem;
|
PBD::Semaphore _callback_start_sem;
|
||||||
PBD::Semaphore _callback_done_sem;
|
PBD::Semaphore _callback_done_sem;
|
||||||
|
|
||||||
/** The number of unprocessed nodes that do not feed any other node; updated during processing */
|
/** The number of unprocessed nodes that do not feed any other node; updated during processing */
|
||||||
std::atomic<unsigned int> _terminal_refcnt;
|
std::atomic<uint32_t> _terminal_refcnt;
|
||||||
|
|
||||||
bool _graph_empty;
|
bool _graph_empty;
|
||||||
|
|
||||||
/* number of background worker threads >= 0 */
|
/* number of background worker threads >= 0 */
|
||||||
std::atomic<unsigned int> _n_workers;
|
std::atomic<uint32_t> _n_workers;
|
||||||
|
|
||||||
/* flag to terminate background threads */
|
/* flag to terminate background threads */
|
||||||
std::atomic<int> _terminate;
|
std::atomic<int> _terminate;
|
||||||
|
|
|
||||||
|
|
@ -73,17 +73,17 @@ public:
|
||||||
|
|
||||||
/** Atomically get both the channel mode and mask. */
|
/** Atomically get both the channel mode and mask. */
|
||||||
void get_mode_and_mask(ChannelMode* mode, uint16_t* mask) const {
|
void get_mode_and_mask(ChannelMode* mode, uint16_t* mask) const {
|
||||||
const uint32_t mm = g_atomic_int_get (const_cast<std::atomic<unsigned int>*> (&_mode_mask));
|
const uint32_t mm = _mode_mask.load();
|
||||||
*mode = static_cast<ChannelMode>((mm & 0xFFFF0000) >> 16);
|
*mode = static_cast<ChannelMode>((mm & 0xFFFF0000) >> 16);
|
||||||
*mask = (mm & 0x0000FFFF);
|
*mask = (mm & 0x0000FFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelMode get_channel_mode() const {
|
ChannelMode get_channel_mode() const {
|
||||||
return static_cast<ChannelMode>((g_atomic_int_get (const_cast<std::atomic<unsigned int>*> (&_mode_mask)) & 0xFFFF0000) >> 16);
|
return static_cast<ChannelMode> ((_mode_mask.load() & 0xFFFF0000) >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t get_channel_mask() const {
|
uint16_t get_channel_mask() const {
|
||||||
return g_atomic_int_get (const_cast<std::atomic<unsigned int>*> (&_mode_mask)) & 0x0000FFFF;
|
return _mode_mask.load() & 0x0000FFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
PBD::Signal0<void> ChannelMaskChanged;
|
PBD::Signal0<void> ChannelMaskChanged;
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ public:
|
||||||
void start_touch (timepos_t const & when);
|
void start_touch (timepos_t const & when);
|
||||||
void stop_touch (timepos_t const & when);
|
void stop_touch (timepos_t const & when);
|
||||||
|
|
||||||
bool touching() const { return g_atomic_int_get (const_cast<std::atomic<int>*> (&_touching)); }
|
bool touching() const { return _touching.load(); }
|
||||||
|
|
||||||
bool writing() const { return _auto_state == Write; }
|
bool writing() const { return _auto_state == Write; }
|
||||||
bool touch_enabled() const { return _auto_state & (Touch | Latch); }
|
bool touch_enabled() const { return _auto_state & (Touch | Latch); }
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ public:
|
||||||
|
|
||||||
virtual void inc_use_count ();
|
virtual void inc_use_count ();
|
||||||
virtual void dec_use_count ();
|
virtual void dec_use_count ();
|
||||||
int use_count() const { return g_atomic_int_get (const_cast<std::atomic<int>*> (&_use_count)); }
|
int use_count() const { return _use_count.load(); }
|
||||||
bool used() const { return use_count() > 0; }
|
bool used() const { return use_count() > 0; }
|
||||||
|
|
||||||
uint32_t level() const { return _level; }
|
uint32_t level() const { return _level; }
|
||||||
|
|
|
||||||
|
|
@ -495,7 +495,7 @@ AUPlugin::discover_factory_presets ()
|
||||||
void
|
void
|
||||||
AUPlugin::init ()
|
AUPlugin::init ()
|
||||||
{
|
{
|
||||||
g_atomic_int_set (&_current_latency, UINT_MAX);
|
_current_latency.store (UINT_MAX);
|
||||||
|
|
||||||
OSErr err;
|
OSErr err;
|
||||||
|
|
||||||
|
|
@ -763,7 +763,7 @@ AUPlugin::plugin_latency () const
|
||||||
guint lat = _current_latency.load ();;
|
guint lat = _current_latency.load ();;
|
||||||
if (lat == UINT_MAX) {
|
if (lat == UINT_MAX) {
|
||||||
lat = unit->Latency() * _session.sample_rate();
|
lat = unit->Latency() * _session.sample_rate();
|
||||||
g_atomic_int_set (&_current_latency, lat);
|
_current_latency.store (lat);
|
||||||
}
|
}
|
||||||
return lat;
|
return lat;
|
||||||
}
|
}
|
||||||
|
|
@ -2660,7 +2660,7 @@ AUPlugin::parameter_change_listener (void* /*arg*/, void* src, const AudioUnitEv
|
||||||
if (event->mArgument.mProperty.mPropertyID == kAudioUnitProperty_Latency) {
|
if (event->mArgument.mProperty.mPropertyID == kAudioUnitProperty_Latency) {
|
||||||
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose("AU Latency Change Event %1 <> %2\n", new_value, unit->Latency()));
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose("AU Latency Change Event %1 <> %2\n", new_value, unit->Latency()));
|
||||||
guint lat = unit->Latency() * _session.sample_rate();
|
guint lat = unit->Latency() * _session.sample_rate();
|
||||||
g_atomic_int_set (&_current_latency, lat);
|
_current_latency.store (lat);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ AutomationList::AutomationList (const AutomationList& other)
|
||||||
, _before (0)
|
, _before (0)
|
||||||
{
|
{
|
||||||
_state = other._state;
|
_state = other._state;
|
||||||
g_atomic_int_set (&_touching, other.touching());
|
_touching.store (other.touching());
|
||||||
|
|
||||||
create_curve_if_necessary();
|
create_curve_if_necessary();
|
||||||
|
|
||||||
|
|
@ -108,7 +108,7 @@ AutomationList::AutomationList (const AutomationList& other, timepos_t const & s
|
||||||
, _before (0)
|
, _before (0)
|
||||||
{
|
{
|
||||||
_state = other._state;
|
_state = other._state;
|
||||||
g_atomic_int_set (&_touching, other.touching());
|
_touching.store (other.touching());
|
||||||
|
|
||||||
create_curve_if_necessary();
|
create_curve_if_necessary();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,15 @@
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
CircularSampleBuffer::CircularSampleBuffer (samplecnt_t size)
|
CircularSampleBuffer::CircularSampleBuffer (size_t size)
|
||||||
: _rb (size)
|
: _rb (size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CircularSampleBuffer::write (Sample const* buf, samplecnt_t n_samples)
|
CircularSampleBuffer::write (Sample const* buf, size_t n_samples)
|
||||||
{
|
{
|
||||||
ssize_t ws = (ssize_t) _rb.write_space ();
|
size_t ws = _rb.write_space ();
|
||||||
if (ws < n_samples) {
|
if (ws < n_samples) {
|
||||||
/* overwrite old data (consider a spinlock wrt ::read) */
|
/* overwrite old data (consider a spinlock wrt ::read) */
|
||||||
_rb.increment_read_idx (n_samples - ws);
|
_rb.increment_read_idx (n_samples - ws);
|
||||||
|
|
@ -38,16 +38,16 @@ CircularSampleBuffer::write (Sample const* buf, samplecnt_t n_samples)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CircularSampleBuffer::silence (samplecnt_t n_samples)
|
CircularSampleBuffer::silence (size_t n_samples)
|
||||||
{
|
{
|
||||||
ssize_t ws = (ssize_t) _rb.write_space ();
|
size_t ws = _rb.write_space ();
|
||||||
if (ws < n_samples) {
|
if (ws < n_samples) {
|
||||||
/* overwrite old data (consider a spinlock wrt ::read) */
|
/* overwrite old data (consider a spinlock wrt ::read) */
|
||||||
_rb.increment_read_idx (n_samples - ws);
|
_rb.increment_read_idx (n_samples - ws);
|
||||||
}
|
}
|
||||||
PBD::RingBuffer<Sample>::rw_vector vec;
|
PBD::RingBuffer<Sample>::rw_vector vec;
|
||||||
_rb.get_write_vector (&vec);
|
_rb.get_write_vector (&vec);
|
||||||
if (vec.len[0] >= n_samples) {
|
if (vec.len[0] >= (size_t) n_samples) {
|
||||||
memset (vec.buf[0], 0, sizeof (Sample) * n_samples);
|
memset (vec.buf[0], 0, sizeof (Sample) * n_samples);
|
||||||
} else {
|
} else {
|
||||||
assert (vec.len[0] > 0 && vec.len[0] + vec.len[1] >= n_samples);
|
assert (vec.len[0] > 0 && vec.len[0] + vec.len[1] >= n_samples);
|
||||||
|
|
@ -58,7 +58,7 @@ CircularSampleBuffer::silence (samplecnt_t n_samples)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CircularSampleBuffer::read (Sample& s_min, Sample& s_max, samplecnt_t spp)
|
CircularSampleBuffer::read (Sample& s_min, Sample& s_max, size_t spp)
|
||||||
{
|
{
|
||||||
s_min = s_max = 0;
|
s_min = s_max = 0;
|
||||||
|
|
||||||
|
|
@ -72,10 +72,10 @@ CircularSampleBuffer::read (Sample& s_min, Sample& s_max, samplecnt_t spp)
|
||||||
/* immediately mark as read, allow writer to overwrite data if needed */
|
/* immediately mark as read, allow writer to overwrite data if needed */
|
||||||
_rb.increment_read_idx (spp);
|
_rb.increment_read_idx (spp);
|
||||||
|
|
||||||
samplecnt_t to_proc = std::min (spp, (samplecnt_t)vec.len[0]);
|
size_t to_proc = std::min (spp, vec.len[0]);
|
||||||
ARDOUR::find_peaks (vec.buf[0], to_proc, &s_min, &s_max);
|
ARDOUR::find_peaks (vec.buf[0], to_proc, &s_min, &s_max);
|
||||||
|
|
||||||
to_proc = std::min (spp - to_proc, (samplecnt_t)vec.len[1]);
|
to_proc = std::min (spp - to_proc, vec.len[1]);
|
||||||
if (to_proc > 0) { // XXX is this check needed?
|
if (to_proc > 0) { // XXX is this check needed?
|
||||||
ARDOUR::find_peaks (vec.buf[1], to_proc, &s_min, &s_max);
|
ARDOUR::find_peaks (vec.buf[1], to_proc, &s_min, &s_max);
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +111,7 @@ CircularEventBuffer::Event::Event (uint8_t const* buf, size_t size)
|
||||||
pad = 0;
|
pad = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CircularEventBuffer::CircularEventBuffer (samplecnt_t size)
|
CircularEventBuffer::CircularEventBuffer (size_t size)
|
||||||
{
|
{
|
||||||
guint power_of_two;
|
guint power_of_two;
|
||||||
for (power_of_two = 1; 1U << power_of_two < size; ++power_of_two) {}
|
for (power_of_two = 1; 1U << power_of_two < size; ++power_of_two) {}
|
||||||
|
|
@ -142,7 +142,7 @@ CircularEventBuffer::write (uint8_t const* buf, size_t size)
|
||||||
guint write_idx = _idx.load ();
|
guint write_idx = _idx.load ();
|
||||||
memcpy (&_buf[write_idx], &e, sizeof (Event));
|
memcpy (&_buf[write_idx], &e, sizeof (Event));
|
||||||
write_idx = (write_idx + 1) & _size_mask;
|
write_idx = (write_idx + 1) & _size_mask;
|
||||||
g_atomic_int_set (&_idx, write_idx);
|
_idx.store (write_idx);
|
||||||
_ack.store (1);
|
_ack.store (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ bool
|
||||||
CircularEventBuffer::read (EventList& l)
|
CircularEventBuffer::read (EventList& l)
|
||||||
{
|
{
|
||||||
guint to_read = _size_mask;
|
guint to_read = _size_mask;
|
||||||
int canderef (1);
|
size_t canderef (1);
|
||||||
if (!_ack.compare_exchange_strong (canderef, 0)) {
|
if (!_ack.compare_exchange_strong (canderef, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -687,10 +687,10 @@ DiskReader::overwrite_existing_audio ()
|
||||||
const bool reversed = !_session.transport_will_roll_forwards ();
|
const bool reversed = !_session.transport_will_roll_forwards ();
|
||||||
|
|
||||||
sampleoffset_t chunk1_offset;
|
sampleoffset_t chunk1_offset;
|
||||||
samplecnt_t chunk1_cnt;
|
size_t chunk1_cnt;
|
||||||
samplecnt_t chunk2_cnt;
|
size_t chunk2_cnt;
|
||||||
|
|
||||||
const samplecnt_t to_overwrite = c->front()->rbuf->overwritable_at (overwrite_offset);
|
const size_t to_overwrite = c->front()->rbuf->overwritable_at (overwrite_offset);
|
||||||
|
|
||||||
chunk1_offset = overwrite_offset;
|
chunk1_offset = overwrite_offset;
|
||||||
chunk1_cnt = min (c->front()->rbuf->bufsize() - overwrite_offset, to_overwrite);
|
chunk1_cnt = min (c->front()->rbuf->bufsize() - overwrite_offset, to_overwrite);
|
||||||
|
|
@ -728,7 +728,7 @@ DiskReader::overwrite_existing_audio ()
|
||||||
start = overwrite_sample;
|
start = overwrite_sample;
|
||||||
|
|
||||||
if (chunk1_cnt) {
|
if (chunk1_cnt) {
|
||||||
if (audio_read (buf + chunk1_offset, mixdown_buffer.get (), gain_buffer.get (), start, chunk1_cnt, rci, n, reversed) != chunk1_cnt) {
|
if (audio_read (buf + chunk1_offset, mixdown_buffer.get (), gain_buffer.get (), start, chunk1_cnt, rci, n, reversed) != (samplecnt_t) chunk1_cnt) {
|
||||||
error << string_compose (_("DiskReader %1: when overwriting(1), cannot read %2 from playlist at sample %3"), id (), chunk1_cnt, overwrite_sample) << endmsg;
|
error << string_compose (_("DiskReader %1: when overwriting(1), cannot read %2 from playlist at sample %3"), id (), chunk1_cnt, overwrite_sample) << endmsg;
|
||||||
ret = false;
|
ret = false;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -737,7 +737,7 @@ DiskReader::overwrite_existing_audio ()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chunk2_cnt) {
|
if (chunk2_cnt) {
|
||||||
if (audio_read (buf, mixdown_buffer.get (), gain_buffer.get (), start, chunk2_cnt, rci, n, reversed) != chunk2_cnt) {
|
if (audio_read (buf, mixdown_buffer.get (), gain_buffer.get (), start, chunk2_cnt, rci, n, reversed) != (samplecnt_t) chunk2_cnt) {
|
||||||
error << string_compose (_("DiskReader %1: when overwriting(2), cannot read %2 from playlist at sample %3"), id (), chunk2_cnt, overwrite_sample) << endmsg;
|
error << string_compose (_("DiskReader %1: when overwriting(2), cannot read %2 from playlist at sample %3"), id (), chunk2_cnt, overwrite_sample) << endmsg;
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
|
|
@ -837,7 +837,7 @@ DiskReader::seek (samplepos_t sample, bool complete_refill)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abs (sample - playback_sample) < (c->front ()->rbuf->reserved_size () / 6)) {
|
if ((size_t) abs (sample - playback_sample) < (c->front ()->rbuf->reserved_size () / 6)) {
|
||||||
/* we're close enough. Note: this is a heuristic */
|
/* we're close enough. Note: this is a heuristic */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -865,7 +865,8 @@ DiskReader::seek (samplepos_t sample, bool complete_refill)
|
||||||
* samples.
|
* samples.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
samplecnt_t shift = sample > c->front ()->rbuf->reservation_size () ? c->front ()->rbuf->reservation_size () : sample;
|
const samplecnt_t rsize = (samplecnt_t) c->front()->rbuf->reservation_size();
|
||||||
|
samplecnt_t shift = (sample > rsize ? rsize : sample);
|
||||||
|
|
||||||
if (read_reversed) {
|
if (read_reversed) {
|
||||||
/* reading in reverse, so start at a later sample, and read
|
/* reading in reverse, so start at a later sample, and read
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,7 @@ DiskWriter::set_state (const XMLNode& node, int version)
|
||||||
|
|
||||||
int rec_safe = 0;
|
int rec_safe = 0;
|
||||||
node.get_property (X_("record-safe"), rec_safe);
|
node.get_property (X_("record-safe"), rec_safe);
|
||||||
g_atomic_int_set (&_record_safe, rec_safe);
|
_record_safe.store (rec_safe);
|
||||||
|
|
||||||
reset_write_sources (false, true);
|
reset_write_sources (false, true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,6 @@ alloc_allowed ()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define g_atomic_uint_get(x) static_cast<guint> (g_atomic_int_get (x))
|
|
||||||
|
|
||||||
Graph::Graph (Session& session)
|
Graph::Graph (Session& session)
|
||||||
: SessionHandleRef (session)
|
: SessionHandleRef (session)
|
||||||
, _execution_sem ("graph_execution", 0)
|
, _execution_sem ("graph_execution", 0)
|
||||||
|
|
@ -107,7 +105,7 @@ void
|
||||||
Graph::reset_thread_list ()
|
Graph::reset_thread_list ()
|
||||||
{
|
{
|
||||||
uint32_t num_threads = how_many_dsp_threads ();
|
uint32_t num_threads = how_many_dsp_threads ();
|
||||||
guint n_workers = g_atomic_uint_get (&_n_workers);
|
uint32_t n_workers = _n_workers.load();
|
||||||
|
|
||||||
/* don't bother doing anything here if we already have the right
|
/* don't bother doing anything here if we already have the right
|
||||||
* number of threads.
|
* number of threads.
|
||||||
|
|
@ -136,7 +134,7 @@ Graph::reset_thread_list ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (g_atomic_uint_get (&_n_workers) + 1 != num_threads) {
|
while (_n_workers.load() + 1 != num_threads) {
|
||||||
sched_yield ();
|
sched_yield ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +142,7 @@ Graph::reset_thread_list ()
|
||||||
uint32_t
|
uint32_t
|
||||||
Graph::n_threads () const
|
Graph::n_threads () const
|
||||||
{
|
{
|
||||||
return 1 + g_atomic_uint_get (&_n_workers);
|
return 1 + _n_workers.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -165,8 +163,8 @@ Graph::drop_threads ()
|
||||||
_terminate.store (1);
|
_terminate.store (1);
|
||||||
|
|
||||||
/* Wake-up sleeping threads */
|
/* Wake-up sleeping threads */
|
||||||
guint tc = g_atomic_uint_get (&_idle_thread_cnt);
|
uint32_t tc = _idle_thread_cnt.load();
|
||||||
assert (tc == g_atomic_uint_get (&_n_workers));
|
assert (tc == _n_workers.load());
|
||||||
for (guint i = 0; i < tc; ++i) {
|
for (guint i = 0; i < tc; ++i) {
|
||||||
_execution_sem.signal ();
|
_execution_sem.signal ();
|
||||||
}
|
}
|
||||||
|
|
@ -213,14 +211,14 @@ Graph::prep ()
|
||||||
_graph_empty = false;
|
_graph_empty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (g_atomic_uint_get (&_trigger_queue_size) == 0);
|
assert (_trigger_queue_size.load() == 0);
|
||||||
assert (_graph_empty != (_graph_chain->_n_terminal_nodes > 0));
|
assert (_graph_empty != (_graph_chain->_n_terminal_nodes > 0));
|
||||||
|
|
||||||
if (_trigger_queue.capacity () < _graph_chain->_nodes_rt.size ()) {
|
if (_trigger_queue.capacity () < _graph_chain->_nodes_rt.size ()) {
|
||||||
_trigger_queue.reserve (_graph_chain->_nodes_rt.size ());
|
_trigger_queue.reserve (_graph_chain->_nodes_rt.size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
g_atomic_int_set (&_terminal_refcnt, _graph_chain->_n_terminal_nodes);
|
_terminal_refcnt.store (_graph_chain->_n_terminal_nodes);
|
||||||
|
|
||||||
/* Trigger the initial nodes for processing, which are the ones at the `input' end */
|
/* Trigger the initial nodes for processing, which are the ones at the `input' end */
|
||||||
for (auto const& i : _graph_chain->_init_trigger_list) {
|
for (auto const& i : _graph_chain->_init_trigger_list) {
|
||||||
|
|
@ -248,7 +246,7 @@ Graph::reached_terminal_node ()
|
||||||
/* We have run all the nodes that are at the `output' end of
|
/* We have run all the nodes that are at the `output' end of
|
||||||
* the graph, so there is nothing more to do this time around.
|
* the graph, so there is nothing more to do this time around.
|
||||||
*/
|
*/
|
||||||
assert (g_atomic_uint_get (&_trigger_queue_size) == 0);
|
assert (_trigger_queue_size.load() == 0);
|
||||||
|
|
||||||
/* Notify caller */
|
/* Notify caller */
|
||||||
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 cycle done.\n", pthread_name ()));
|
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 cycle done.\n", pthread_name ()));
|
||||||
|
|
@ -260,8 +258,8 @@ Graph::reached_terminal_node ()
|
||||||
* If there are more threads than CPU cores, some worker-
|
* If there are more threads than CPU cores, some worker-
|
||||||
* threads may only be "on the way" to become idle.
|
* threads may only be "on the way" to become idle.
|
||||||
*/
|
*/
|
||||||
guint n_workers = g_atomic_uint_get (&_n_workers);
|
uint32_t n_workers = _n_workers.load();
|
||||||
while (g_atomic_uint_get (&_idle_thread_cnt) != n_workers) {
|
while (_idle_thread_cnt.load() != n_workers) {
|
||||||
sched_yield ();
|
sched_yield ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,9 +301,9 @@ Graph::run_one ()
|
||||||
* other threads.
|
* other threads.
|
||||||
* This thread as not yet decreased _trigger_queue_size.
|
* This thread as not yet decreased _trigger_queue_size.
|
||||||
*/
|
*/
|
||||||
guint idle_cnt = g_atomic_uint_get (&_idle_thread_cnt);
|
uint32_t idle_cnt = _idle_thread_cnt.load();
|
||||||
guint work_avail = g_atomic_uint_get (&_trigger_queue_size);
|
uint32_t work_avail = _trigger_queue_size.load();
|
||||||
guint wakeup = std::min (idle_cnt + 1, work_avail);
|
uint32_t wakeup = std::min (idle_cnt + 1, work_avail);
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 signals %2 threads\n", pthread_name (), wakeup));
|
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 signals %2 threads\n", pthread_name (), wakeup));
|
||||||
for (guint i = 1; i < wakeup; ++i) {
|
for (guint i = 1; i < wakeup; ++i) {
|
||||||
|
|
@ -316,7 +314,7 @@ Graph::run_one ()
|
||||||
while (!to_run) {
|
while (!to_run) {
|
||||||
/* Wait for work, fall asleep */
|
/* Wait for work, fall asleep */
|
||||||
_idle_thread_cnt.fetch_add (1);
|
_idle_thread_cnt.fetch_add (1);
|
||||||
assert (g_atomic_uint_get (&_idle_thread_cnt) <= g_atomic_uint_get (&_n_workers));
|
assert (_idle_thread_cnt.load() <= _n_workers.load());
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 goes to sleep\n", pthread_name ()));
|
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 goes to sleep\n", pthread_name ()));
|
||||||
_execution_sem.wait ();
|
_execution_sem.wait ();
|
||||||
|
|
@ -352,7 +350,7 @@ void
|
||||||
Graph::helper_thread ()
|
Graph::helper_thread ()
|
||||||
{
|
{
|
||||||
_n_workers.fetch_add (1);
|
_n_workers.fetch_add (1);
|
||||||
guint id = g_atomic_uint_get (&_n_workers);
|
uint32_t id = _n_workers.load();
|
||||||
|
|
||||||
/* This is needed for ARDOUR::Session requests called from rt-processors
|
/* This is needed for ARDOUR::Session requests called from rt-processors
|
||||||
* in particular Lua scripts may do cross-thread calls */
|
* in particular Lua scripts may do cross-thread calls */
|
||||||
|
|
@ -579,15 +577,15 @@ Graph::in_process_thread () const
|
||||||
void
|
void
|
||||||
Graph::process_tasklist (RTTaskList const& rt)
|
Graph::process_tasklist (RTTaskList const& rt)
|
||||||
{
|
{
|
||||||
assert (g_atomic_uint_get (&_trigger_queue_size) == 0);
|
assert (_trigger_queue_size.load() == 0);
|
||||||
|
|
||||||
std::vector<RTTask> const& tasks = rt.tasks ();
|
std::vector<RTTask> const& tasks = rt.tasks ();
|
||||||
if (tasks.empty ()) {
|
if (tasks.empty ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_atomic_int_set (&_trigger_queue_size, tasks.size ());
|
_trigger_queue_size.store (tasks.size ());
|
||||||
g_atomic_int_set (&_terminal_refcnt, tasks.size ());
|
_terminal_refcnt.store (tasks.size ());
|
||||||
_graph_empty = false;
|
_graph_empty = false;
|
||||||
|
|
||||||
for (auto const& t : tasks) {
|
for (auto const& t : tasks) {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ void
|
||||||
GraphNode::prep (GraphChain const* chain)
|
GraphNode::prep (GraphChain const* chain)
|
||||||
{
|
{
|
||||||
/* This is the number of nodes that directly feed us */
|
/* This is the number of nodes that directly feed us */
|
||||||
g_atomic_int_set (&_refcount, init_refcount (chain));
|
_refcount.store (init_refcount (chain));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -76,7 +76,7 @@ GraphNode::trigger ()
|
||||||
if (PBD::atomic_dec_and_test (_refcount)) {
|
if (PBD::atomic_dec_and_test (_refcount)) {
|
||||||
#if 0 // TODO optimize: remove prep()
|
#if 0 // TODO optimize: remove prep()
|
||||||
/* reset reference count for next cycle */
|
/* reset reference count for next cycle */
|
||||||
g_atomic_int_set (&_refcount, _init_refcount[chain]);
|
_refcount.store (_init_refcount[chain]);
|
||||||
#endif
|
#endif
|
||||||
/* All nodes that feed this node have completed, so this node be processed now. */
|
/* All nodes that feed this node have completed, so this node be processed now. */
|
||||||
_graph->trigger (this);
|
_graph->trigger (this);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace ARDOUR {
|
||||||
|
|
||||||
MidiChannelFilter::MidiChannelFilter()
|
MidiChannelFilter::MidiChannelFilter()
|
||||||
{
|
{
|
||||||
g_atomic_int_set (&_mode_mask, 0x0000FFFF);
|
_mode_mask.store (0x0000FFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -115,7 +115,7 @@ MidiChannelFilter::set_channel_mode(ChannelMode mode, uint16_t mask)
|
||||||
|
|
||||||
if (old_mode != mode || old_mask != mask) {
|
if (old_mode != mode || old_mask != mask) {
|
||||||
mask = force_mask(mode, mask);
|
mask = force_mask(mode, mask);
|
||||||
g_atomic_int_set (&_mode_mask, (uint32_t(mode) << 16) | uint32_t(mask));
|
_mode_mask.store ((uint32_t(mode) << 16) | uint32_t(mask));
|
||||||
ChannelModeChanged();
|
ChannelModeChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +132,7 @@ MidiChannelFilter::set_channel_mask(uint16_t mask)
|
||||||
|
|
||||||
if (old_mask != mask) {
|
if (old_mask != mask) {
|
||||||
mask = force_mask(mode, mask);
|
mask = force_mask(mode, mask);
|
||||||
g_atomic_int_set (&_mode_mask, (uint32_t(mode) << 16) | uint32_t(mask));
|
_mode_mask.store ((uint32_t(mode) << 16) | uint32_t(mask));
|
||||||
ChannelMaskChanged();
|
ChannelMaskChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4133,7 +4133,7 @@ Route::apply_processor_changes_rt ()
|
||||||
update_signal_latency (true);
|
update_signal_latency (true);
|
||||||
}
|
}
|
||||||
if (emissions != 0) {
|
if (emissions != 0) {
|
||||||
g_atomic_int_set (&_pending_signals, emissions);
|
_pending_signals.store (emissions);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (!selfdestruct_sequence.empty ());
|
return (!selfdestruct_sequence.empty ());
|
||||||
|
|
|
||||||
|
|
@ -1499,7 +1499,7 @@ Session::reset_punch_loop_constraint ()
|
||||||
if (_punch_or_loop.load () == NoConstraint) {
|
if (_punch_or_loop.load () == NoConstraint) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_atomic_int_set (&_punch_or_loop, NoConstraint);
|
_punch_or_loop.store (NoConstraint);
|
||||||
PunchLoopConstraintChange (); /* EMIT SIGNAL */
|
PunchLoopConstraintChange (); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1972,11 +1972,11 @@ Session::disable_record (bool rt_context, bool force)
|
||||||
if ((rs = (RecordState) _record_status.load ()) != Disabled) {
|
if ((rs = (RecordState) _record_status.load ()) != Disabled) {
|
||||||
|
|
||||||
if (!Config->get_latched_record_enable () || force) {
|
if (!Config->get_latched_record_enable () || force) {
|
||||||
g_atomic_int_set (&_record_status, Disabled);
|
_record_status.store (Disabled);
|
||||||
send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
|
send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
|
||||||
} else {
|
} else {
|
||||||
if (rs == Recording) {
|
if (rs == Recording) {
|
||||||
g_atomic_int_set (&_record_status, Enabled);
|
_record_status.store (Enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2010,7 +2010,7 @@ Session::maybe_enable_record (bool rt_context)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_atomic_int_set (&_record_status, Enabled);
|
_record_status.store (Enabled);
|
||||||
|
|
||||||
// TODO make configurable, perhaps capture-buffer-seconds dependnet?
|
// TODO make configurable, perhaps capture-buffer-seconds dependnet?
|
||||||
bool quick_start = true;
|
bool quick_start = true;
|
||||||
|
|
@ -6322,7 +6322,7 @@ Session::update_route_record_state ()
|
||||||
|
|
||||||
int const old = _have_rec_enabled_track.load ();
|
int const old = _have_rec_enabled_track.load ();
|
||||||
|
|
||||||
g_atomic_int_set (&_have_rec_enabled_track, i != rl->end () ? 1 : 0);
|
_have_rec_enabled_track.store (i != rl->end () ? 1 : 0);
|
||||||
|
|
||||||
if (_have_rec_enabled_track.load () != old) {
|
if (_have_rec_enabled_track.load () != old) {
|
||||||
RecordStateChanged (); /* EMIT SIGNAL */
|
RecordStateChanged (); /* EMIT SIGNAL */
|
||||||
|
|
@ -6335,7 +6335,7 @@ Session::update_route_record_state ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_atomic_int_set (&_have_rec_disabled_track, i != rl->end () ? 1 : 0);
|
_have_rec_disabled_track.store (i != rl->end () ? 1 : 0);
|
||||||
|
|
||||||
bool record_arm_state_changed = (old != _have_rec_enabled_track.load () );
|
bool record_arm_state_changed = (old != _have_rec_enabled_track.load () );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ Session::mmc_record_strobe (MIDI::MachineControl &/*mmc*/)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
save_state ("", true);
|
save_state ("", true);
|
||||||
g_atomic_int_set (&_record_status, Enabled);
|
_record_status.store (Enabled);
|
||||||
RecordStateChanged (); /* EMIT SIGNAL */
|
RecordStateChanged (); /* EMIT SIGNAL */
|
||||||
|
|
||||||
request_roll (TRS_MMC);
|
request_roll (TRS_MMC);
|
||||||
|
|
|
||||||
|
|
@ -320,8 +320,8 @@ Session::get_track_statistics ()
|
||||||
cworst = min (cworst, tr->capture_buffer_load());
|
cworst = min (cworst, tr->capture_buffer_load());
|
||||||
}
|
}
|
||||||
|
|
||||||
g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
|
_playback_load.store ((uint32_t) floor (pworst * 100.0f));
|
||||||
g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
|
_capture_load.store ((uint32_t) floor (cworst * 100.0f));
|
||||||
|
|
||||||
if (actively_recording()) {
|
if (actively_recording()) {
|
||||||
set_dirty();
|
set_dirty();
|
||||||
|
|
@ -1074,7 +1074,7 @@ Session::process_event (SessionEvent* ev)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SessionEvent::SetTimecodeTransmission:
|
case SessionEvent::SetTimecodeTransmission:
|
||||||
g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
|
_suspend_timecode_transmission.store (ev->yes_or_no ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SessionEvent::SyncCues:
|
case SessionEvent::SyncCues:
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,9 @@ Session::pre_engine_init (string fullpath)
|
||||||
|
|
||||||
timerclear (&last_mmc_step);
|
timerclear (&last_mmc_step);
|
||||||
_processing_prohibited.store (0);
|
_processing_prohibited.store (0);
|
||||||
g_atomic_int_set (&_record_status, Disabled);
|
_record_status.store (Disabled);
|
||||||
g_atomic_int_set (&_playback_load, 100);
|
_playback_load.store (100);
|
||||||
g_atomic_int_set (&_capture_load, 100);
|
_capture_load.store (100);
|
||||||
set_next_event ();
|
set_next_event ();
|
||||||
_all_route_group->set_active (true, this);
|
_all_route_group->set_active (true, this);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,8 +154,8 @@ Session::realtime_stop (bool abort, bool clear_state)
|
||||||
|
|
||||||
reset_punch_loop_constraint ();
|
reset_punch_loop_constraint ();
|
||||||
|
|
||||||
g_atomic_int_set (&_playback_load, 100);
|
_playback_load.store (100);
|
||||||
g_atomic_int_set (&_capture_load, 100);
|
_capture_load.store (100);
|
||||||
|
|
||||||
if (config.get_use_video_sync()) {
|
if (config.get_use_video_sync()) {
|
||||||
waiting_for_sync_offset = true;
|
waiting_for_sync_offset = true;
|
||||||
|
|
@ -1118,7 +1118,7 @@ Session::butler_transport_work (bool have_process_lock)
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
std::shared_ptr<RouteList> r = routes.reader ();
|
std::shared_ptr<RouteList> r = routes.reader ();
|
||||||
int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
|
int on_entry = _butler->should_do_transport_work.load();
|
||||||
bool finished = true;
|
bool finished = true;
|
||||||
PostTransportWork ptw = post_transport_work();
|
PostTransportWork ptw = post_transport_work();
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
@ -1212,7 +1212,7 @@ Session::non_realtime_overwrite (int on_entry, bool& finished, bool update_loop_
|
||||||
if (tr && tr->pending_overwrite ()) {
|
if (tr && tr->pending_overwrite ()) {
|
||||||
tr->overwrite_existing_buffers ();
|
tr->overwrite_existing_buffers ();
|
||||||
}
|
}
|
||||||
if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
|
if (on_entry != _butler->should_do_transport_work.load()) {
|
||||||
finished = false;
|
finished = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1279,14 +1279,14 @@ Session::non_realtime_locate ()
|
||||||
std::cerr << "locate to " << tf << " took " << (end - start) << " usecs for " << nt << " tracks = " << usecs_per_track << " per track\n";
|
std::cerr << "locate to " << tf << " took " << (end - start) << " usecs for " << nt << " tracks = " << usecs_per_track << " per track\n";
|
||||||
#endif
|
#endif
|
||||||
if (usecs_per_track > _current_usecs_per_track.load ()) {
|
if (usecs_per_track > _current_usecs_per_track.load ()) {
|
||||||
g_atomic_int_set (&_current_usecs_per_track, usecs_per_track);
|
_current_usecs_per_track.store (usecs_per_track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we've caught up with whatever the _seek_counter was when we did the
|
/* we've caught up with whatever the _seek_counter was when we did the
|
||||||
non-realtime locates.
|
non-realtime locates.
|
||||||
*/
|
*/
|
||||||
g_atomic_int_set (&_butler_seek_counter, sc);
|
_butler_seek_counter.store (sc);
|
||||||
|
|
||||||
{
|
{
|
||||||
/* VCAs are quick to locate because they have no data (except
|
/* VCAs are quick to locate because they have no data (except
|
||||||
|
|
@ -1510,7 +1510,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished, bool will_
|
||||||
DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
|
DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
|
||||||
(*i)->non_realtime_locate (_transport_sample);
|
(*i)->non_realtime_locate (_transport_sample);
|
||||||
|
|
||||||
if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
|
if (on_entry != _butler->should_do_transport_work.load()) {
|
||||||
finished = false;
|
finished = false;
|
||||||
/* we will be back */
|
/* we will be back */
|
||||||
return;
|
return;
|
||||||
|
|
@ -1998,7 +1998,8 @@ Session::sync_source_changed (SyncSource type, samplepos_t pos, pframes_t cycle_
|
||||||
mtc_master->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
|
mtc_master->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
|
||||||
MTCSyncStateChanged(mtc_master->locked() );
|
MTCSyncStateChanged(mtc_master->locked() );
|
||||||
} else {
|
} else {
|
||||||
if (g_atomic_int_compare_and_exchange (&_mtc_active, 1, 0)) {
|
int canderef (1);
|
||||||
|
if (_mtc_active.compare_exchange_strong (canderef, 0)) {
|
||||||
MTCSyncStateChanged( false );
|
MTCSyncStateChanged( false );
|
||||||
}
|
}
|
||||||
mtc_status_connection.disconnect ();
|
mtc_status_connection.disconnect ();
|
||||||
|
|
@ -2010,7 +2011,8 @@ Session::sync_source_changed (SyncSource type, samplepos_t pos, pframes_t cycle_
|
||||||
ltc_master->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
|
ltc_master->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
|
||||||
LTCSyncStateChanged (ltc_master->locked() );
|
LTCSyncStateChanged (ltc_master->locked() );
|
||||||
} else {
|
} else {
|
||||||
if (g_atomic_int_compare_and_exchange (&_ltc_active, 1, 0)) {
|
int canderef (1);
|
||||||
|
if (_ltc_active.compare_exchange_strong (canderef, 0)) {
|
||||||
LTCSyncStateChanged( false );
|
LTCSyncStateChanged( false );
|
||||||
}
|
}
|
||||||
ltc_status_connection.disconnect ();
|
ltc_status_connection.disconnect ();
|
||||||
|
|
|
||||||
|
|
@ -1265,7 +1265,8 @@ CoreAudioBackend::pre_process ()
|
||||||
bool connections_changed = false;
|
bool connections_changed = false;
|
||||||
bool ports_changed = false;
|
bool ports_changed = false;
|
||||||
if (!pthread_mutex_trylock (&_port_callback_mutex)) {
|
if (!pthread_mutex_trylock (&_port_callback_mutex)) {
|
||||||
if (g_atomic_int_compare_and_exchange (&_port_change_flag, 1, 0)) {
|
int canderef (1);
|
||||||
|
if (_port_change_flag.compare_exchange_strong (canderef, 0)) {
|
||||||
ports_changed = true;
|
ports_changed = true;
|
||||||
}
|
}
|
||||||
if (!_port_connection_queue.empty ()) {
|
if (!_port_connection_queue.empty ()) {
|
||||||
|
|
|
||||||
|
|
@ -1733,7 +1733,8 @@ PortAudioBackend::process_port_connection_changes ()
|
||||||
bool connections_changed = false;
|
bool connections_changed = false;
|
||||||
bool ports_changed = false;
|
bool ports_changed = false;
|
||||||
if (!pthread_mutex_trylock (&_port_callback_mutex)) {
|
if (!pthread_mutex_trylock (&_port_callback_mutex)) {
|
||||||
if (g_atomic_int_compare_and_exchange (&_port_change_flag, 1, 0)) {
|
int canderef (1);
|
||||||
|
if (_port_change_flag.compare_exchange_strong (canderef, 0)) {
|
||||||
ports_changed = true;
|
ports_changed = true;
|
||||||
}
|
}
|
||||||
if (!_port_connection_queue.empty ()) {
|
if (!_port_connection_queue.empty ()) {
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ public:
|
||||||
|
|
||||||
atomic_counter (gint value = 0)
|
atomic_counter (gint value = 0)
|
||||||
{
|
{
|
||||||
g_atomic_int_set (&m_value, value);
|
m_value.store (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
gint get() const
|
gint get() const
|
||||||
|
|
@ -48,7 +48,7 @@ public:
|
||||||
|
|
||||||
void set (gint new_value)
|
void set (gint new_value)
|
||||||
{
|
{
|
||||||
g_atomic_int_set (&m_value, new_value);
|
m_value.store (new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void increment ()
|
void increment ()
|
||||||
|
|
@ -73,12 +73,7 @@ public:
|
||||||
|
|
||||||
bool compare_and_exchange (gint old_value, gint new_value)
|
bool compare_and_exchange (gint old_value, gint new_value)
|
||||||
{
|
{
|
||||||
return g_atomic_int_compare_and_exchange
|
return m_value.compare_exchange_strong (old_value, new_value);
|
||||||
(
|
|
||||||
&m_value,
|
|
||||||
old_value,
|
|
||||||
new_value
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -20,21 +20,12 @@
|
||||||
#ifndef _pbd_mpc_queue_h_
|
#ifndef _pbd_mpc_queue_h_
|
||||||
#define _pbd_mpc_queue_h_
|
#define _pbd_mpc_queue_h_
|
||||||
|
|
||||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
|
||||||
# define MPMC_USE_STD_ATOMIC 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
# include <atomic>
|
# include <atomic>
|
||||||
# define MPMC_QUEUE_TYPE std::atomic<size_t>
|
# define MPMC_QUEUE_TYPE std::atomic<size_t>
|
||||||
#else
|
|
||||||
# include <glib.h>
|
|
||||||
# define MPMC_QUEUE_TYPE std::atomic<unsigned int>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace PBD {
|
namespace PBD {
|
||||||
|
|
||||||
|
|
@ -88,64 +79,37 @@ public:
|
||||||
void
|
void
|
||||||
clear ()
|
clear ()
|
||||||
{
|
{
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
for (size_t i = 0; i <= _buffer_mask; ++i) {
|
for (size_t i = 0; i <= _buffer_mask; ++i) {
|
||||||
_buffer[i]._sequence.store (i, std::memory_order_relaxed);
|
_buffer[i]._sequence.store (i, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
_enqueue_pos.store (0, std::memory_order_relaxed);
|
_enqueue_pos.store (0, std::memory_order_relaxed);
|
||||||
_dequeue_pos.store (0, std::memory_order_relaxed);
|
_dequeue_pos.store (0, std::memory_order_relaxed);
|
||||||
#else
|
|
||||||
for (size_t i = 0; i <= _buffer_mask; ++i) {
|
|
||||||
g_atomic_int_set (&_buffer[i]._sequence, i);
|
|
||||||
}
|
|
||||||
_enqueue_pos.store (0);
|
|
||||||
_dequeue_pos.store (0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
push_back (T const& data)
|
push_back (T const& data)
|
||||||
{
|
{
|
||||||
cell_t* cell;
|
cell_t* cell;
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
size_t pos = _enqueue_pos.load (std::memory_order_relaxed);
|
size_t pos = _enqueue_pos.load (std::memory_order_relaxed);
|
||||||
#else
|
|
||||||
guint pos = _enqueue_pos.load ();
|
|
||||||
#endif
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
cell = &_buffer[pos & _buffer_mask];
|
cell = &_buffer[pos & _buffer_mask];
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
size_t seq = cell->_sequence.load (std::memory_order_acquire);
|
size_t seq = cell->_sequence.load (std::memory_order_acquire);
|
||||||
#else
|
|
||||||
guint seq = g_atomic_int_get (&cell->_sequence);
|
|
||||||
#endif
|
|
||||||
intptr_t dif = (intptr_t)seq - (intptr_t)pos;
|
intptr_t dif = (intptr_t)seq - (intptr_t)pos;
|
||||||
if (dif == 0) {
|
if (dif == 0) {
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
if (_enqueue_pos.compare_exchange_weak (pos, pos + 1, std::memory_order_relaxed))
|
if (_enqueue_pos.compare_exchange_weak (pos, pos + 1, std::memory_order_relaxed))
|
||||||
#else
|
|
||||||
if (g_atomic_int_compare_and_exchange (&_enqueue_pos, pos, pos + 1))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (dif < 0) {
|
} else if (dif < 0) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
pos = _enqueue_pos.load (std::memory_order_relaxed);
|
pos = _enqueue_pos.load (std::memory_order_relaxed);
|
||||||
#else
|
|
||||||
pos = _enqueue_pos.load ();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->_data = data;
|
cell->_data = data;
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
cell->_sequence.store (pos + 1, std::memory_order_release);
|
cell->_sequence.store (pos + 1, std::memory_order_release);
|
||||||
#else
|
|
||||||
g_atomic_int_set (&cell->_sequence, pos + 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -154,45 +118,26 @@ public:
|
||||||
pop_front (T& data)
|
pop_front (T& data)
|
||||||
{
|
{
|
||||||
cell_t* cell;
|
cell_t* cell;
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
size_t pos = _dequeue_pos.load (std::memory_order_relaxed);
|
size_t pos = _dequeue_pos.load (std::memory_order_relaxed);
|
||||||
#else
|
|
||||||
guint pos = _dequeue_pos.load ();
|
|
||||||
#endif
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
cell = &_buffer[pos & _buffer_mask];
|
cell = &_buffer[pos & _buffer_mask];
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
size_t seq = cell->_sequence.load (std::memory_order_acquire);
|
size_t seq = cell->_sequence.load (std::memory_order_acquire);
|
||||||
#else
|
|
||||||
guint seq = g_atomic_int_get (&cell->_sequence);
|
|
||||||
#endif
|
|
||||||
intptr_t dif = (intptr_t)seq - (intptr_t) (pos + 1);
|
intptr_t dif = (intptr_t)seq - (intptr_t) (pos + 1);
|
||||||
if (dif == 0) {
|
if (dif == 0) {
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
if (_dequeue_pos.compare_exchange_weak (pos, pos + 1, std::memory_order_relaxed))
|
if (_dequeue_pos.compare_exchange_weak (pos, pos + 1, std::memory_order_relaxed))
|
||||||
#else
|
|
||||||
if (g_atomic_int_compare_and_exchange (&_dequeue_pos, pos, pos + 1))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (dif < 0) {
|
} else if (dif < 0) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
pos = _dequeue_pos.load (std::memory_order_relaxed);
|
pos = _dequeue_pos.load (std::memory_order_relaxed);
|
||||||
#else
|
|
||||||
pos = _dequeue_pos.load ();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data = cell->_data;
|
data = cell->_data;
|
||||||
#ifdef MPMC_USE_STD_ATOMIC
|
|
||||||
cell->_sequence.store (pos + _buffer_mask + 1, std::memory_order_release);
|
cell->_sequence.store (pos + _buffer_mask + 1, std::memory_order_release);
|
||||||
#else
|
|
||||||
g_atomic_int_set (&cell->_sequence, pos + _buffer_mask + 1);
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,7 +159,6 @@ private:
|
||||||
|
|
||||||
} // namespace PBD
|
} // namespace PBD
|
||||||
|
|
||||||
#undef MPMC_USE_STD_ATOMIC
|
|
||||||
#undef MPMC_QUEUE_TYPE
|
#undef MPMC_QUEUE_TYPE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,13 @@ template<class T>
|
||||||
class /*LIBPBD_API*/ PlaybackBuffer
|
class /*LIBPBD_API*/ PlaybackBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static guint power_of_two_size (guint sz) {
|
static size_t power_of_two_size (size_t sz) {
|
||||||
int32_t power_of_two;
|
int32_t power_of_two;
|
||||||
for (power_of_two = 1; 1U << power_of_two < sz; ++power_of_two);
|
for (power_of_two = 1; 1U << power_of_two < sz; ++power_of_two);
|
||||||
return 1U << power_of_two;
|
return 1U << power_of_two;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaybackBuffer (guint sz, guint res = 8191)
|
PlaybackBuffer (size_t sz, size_t res = 8191)
|
||||||
: reservation (res)
|
: reservation (res)
|
||||||
{
|
{
|
||||||
sz += reservation;
|
sz += reservation;
|
||||||
|
|
@ -60,7 +60,7 @@ public:
|
||||||
/* init (mlock) */
|
/* init (mlock) */
|
||||||
T *buffer () { return buf; }
|
T *buffer () { return buf; }
|
||||||
/* init (mlock) */
|
/* init (mlock) */
|
||||||
guint bufsize () const { return size; }
|
size_t bufsize () const { return size; }
|
||||||
|
|
||||||
/* write-thread */
|
/* write-thread */
|
||||||
void reset () {
|
void reset () {
|
||||||
|
|
@ -75,20 +75,20 @@ public:
|
||||||
/* called from rt (reader) thread for new buffers */
|
/* called from rt (reader) thread for new buffers */
|
||||||
void align_to (PlaybackBuffer const& other) {
|
void align_to (PlaybackBuffer const& other) {
|
||||||
Glib::Threads::Mutex::Lock lm (_reset_lock);
|
Glib::Threads::Mutex::Lock lm (_reset_lock);
|
||||||
g_atomic_int_set (&read_idx, g_atomic_int_get (&other.read_idx));
|
read_idx.store (other.read_idx.load());
|
||||||
g_atomic_int_set (&write_idx, g_atomic_int_get (&other.write_idx));
|
write_idx.store (other.write_idx.load());
|
||||||
g_atomic_int_set (&reserved, g_atomic_int_get (&other.reserved));
|
reserved.store (other.reserved.load());
|
||||||
memset (buf, 0, size * sizeof (T));
|
memset (buf, 0, size * sizeof (T));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write-thread */
|
/* write-thread */
|
||||||
guint write_space () const {
|
size_t write_space () const {
|
||||||
guint w, r;
|
size_t w, r;
|
||||||
|
|
||||||
w = write_idx.load ();
|
w = write_idx.load ();
|
||||||
r = read_idx.load ();
|
r = read_idx.load ();
|
||||||
|
|
||||||
guint rv;
|
size_t rv;
|
||||||
|
|
||||||
if (w > r) {
|
if (w > r) {
|
||||||
rv = ((r + size) - w) & size_mask;
|
rv = ((r + size) - w) & size_mask;
|
||||||
|
|
@ -111,8 +111,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read-thread */
|
/* read-thread */
|
||||||
guint read_space () const {
|
size_t read_space () const {
|
||||||
guint w, r;
|
size_t w, r;
|
||||||
|
|
||||||
w = write_idx.load ();
|
w = write_idx.load ();
|
||||||
r = read_idx.load ();
|
r = read_idx.load ();
|
||||||
|
|
@ -125,8 +125,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write thread */
|
/* write thread */
|
||||||
guint overwritable_at (guint r) const {
|
size_t overwritable_at (size_t r) const {
|
||||||
guint w;
|
size_t w;
|
||||||
|
|
||||||
w = write_idx.load ();
|
w = write_idx.load ();
|
||||||
|
|
||||||
|
|
@ -137,26 +137,26 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read-thead */
|
/* read-thead */
|
||||||
guint read (T *dest, guint cnt, bool commit = true, guint offset = 0);
|
size_t read (T *dest, size_t cnt, bool commit = true, size_t offset = 0);
|
||||||
|
|
||||||
/* write-thead */
|
/* write-thead */
|
||||||
guint write (T const * src, guint cnt);
|
size_t write (T const * src, size_t cnt);
|
||||||
/* write-thead */
|
/* write-thead */
|
||||||
guint write_zero (guint cnt);
|
size_t write_zero (size_t cnt);
|
||||||
/* read-thead */
|
/* read-thead */
|
||||||
guint increment_write_ptr (guint cnt)
|
size_t increment_write_ptr (size_t cnt)
|
||||||
{
|
{
|
||||||
cnt = std::min (cnt, write_space ());
|
cnt = std::min (cnt, write_space ());
|
||||||
g_atomic_int_set (&write_idx, (write_idx.load () + cnt) & size_mask);
|
write_idx.store ((write_idx.load () + cnt) & size_mask);
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read-thead */
|
/* read-thead */
|
||||||
guint decrement_read_ptr (guint cnt)
|
size_t decrement_read_ptr (size_t cnt)
|
||||||
{
|
{
|
||||||
SpinLock sl (_reservation_lock);
|
SpinLock sl (_reservation_lock);
|
||||||
guint r = read_idx.load ();
|
size_t r = read_idx.load ();
|
||||||
guint res = reserved.load ();
|
size_t res = reserved.load ();
|
||||||
|
|
||||||
cnt = std::min (cnt, res);
|
cnt = std::min (cnt, res);
|
||||||
|
|
||||||
|
|
@ -164,19 +164,19 @@ public:
|
||||||
res -= cnt;
|
res -= cnt;
|
||||||
|
|
||||||
read_idx.store (r);
|
read_idx.store (r);
|
||||||
g_atomic_int_set (&reserved, res);
|
reserved.store (res);
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read-thead */
|
/* read-thead */
|
||||||
guint increment_read_ptr (guint cnt)
|
size_t increment_read_ptr (size_t cnt)
|
||||||
{
|
{
|
||||||
cnt = std::min (cnt, read_space ());
|
cnt = std::min (cnt, read_space ());
|
||||||
|
|
||||||
SpinLock sl (_reservation_lock);
|
SpinLock sl (_reservation_lock);
|
||||||
g_atomic_int_set (&read_idx, (read_idx.load () + cnt) & size_mask);
|
read_idx.store ((read_idx.load () + cnt) & size_mask);
|
||||||
g_atomic_int_set (&reserved, std::min (reservation, reserved.load () + cnt));
|
reserved.store (std::min (reservation, reserved.load () + cnt));
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
@ -184,28 +184,28 @@ public:
|
||||||
/* read-thead */
|
/* read-thead */
|
||||||
bool can_seek (int64_t cnt) {
|
bool can_seek (int64_t cnt) {
|
||||||
if (cnt > 0) {
|
if (cnt > 0) {
|
||||||
return read_space() >= cnt;
|
return read_space() >= (size_t) cnt;
|
||||||
} else if (cnt < 0) {
|
} else if (cnt < 0) {
|
||||||
return reserved.load () >= -cnt;
|
return reserved.load () >= (size_t) -cnt;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
guint read_ptr() const { return read_idx.load (); }
|
size_t read_ptr() const { return read_idx.load (); }
|
||||||
guint write_ptr() const { return write_idx.load (); }
|
size_t write_ptr() const { return write_idx.load (); }
|
||||||
guint reserved_size() const { return reserved.load (); }
|
size_t reserved_size() const { return reserved.load (); }
|
||||||
guint reservation_size() const { return reservation; }
|
size_t reservation_size() const { return reservation; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T *buf;
|
T *buf;
|
||||||
const guint reservation;
|
const size_t reservation;
|
||||||
guint size;
|
size_t size;
|
||||||
guint size_mask;
|
size_t size_mask;
|
||||||
|
|
||||||
mutable std::atomic<int> write_idx;
|
mutable std::atomic<size_t> write_idx;
|
||||||
mutable std::atomic<int> read_idx;
|
mutable std::atomic<size_t> read_idx;
|
||||||
mutable std::atomic<int> reserved;
|
mutable std::atomic<size_t> reserved;
|
||||||
|
|
||||||
/* spinlock will be used to update write_idx and reserved in sync */
|
/* spinlock will be used to update write_idx and reserved in sync */
|
||||||
spinlock_t _reservation_lock;
|
spinlock_t _reservation_lock;
|
||||||
|
|
@ -213,20 +213,20 @@ private:
|
||||||
Glib::Threads::Mutex _reset_lock;
|
Glib::Threads::Mutex _reset_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> /*LIBPBD_API*/ guint
|
template<class T> /*LIBPBD_API*/ size_t
|
||||||
PlaybackBuffer<T>::write (T const *src, guint cnt)
|
PlaybackBuffer<T>::write (T const *src, size_t cnt)
|
||||||
{
|
{
|
||||||
guint w = write_idx.load ();
|
size_t w = write_idx.load ();
|
||||||
const guint free_cnt = write_space ();
|
const size_t free_cnt = write_space ();
|
||||||
|
|
||||||
if (free_cnt == 0) {
|
if (free_cnt == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const guint to_write = cnt > free_cnt ? free_cnt : cnt;
|
const size_t to_write = cnt > free_cnt ? free_cnt : cnt;
|
||||||
const guint cnt2 = w + to_write;
|
const size_t cnt2 = w + to_write;
|
||||||
|
|
||||||
guint n1, n2;
|
size_t n1, n2;
|
||||||
if (cnt2 > size) {
|
if (cnt2 > size) {
|
||||||
n1 = size - w;
|
n1 = size - w;
|
||||||
n2 = cnt2 & size_mask;
|
n2 = cnt2 & size_mask;
|
||||||
|
|
@ -247,20 +247,20 @@ PlaybackBuffer<T>::write (T const *src, guint cnt)
|
||||||
return to_write;
|
return to_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> /*LIBPBD_API*/ guint
|
template<class T> /*LIBPBD_API*/ size_t
|
||||||
PlaybackBuffer<T>::write_zero (guint cnt)
|
PlaybackBuffer<T>::write_zero (size_t cnt)
|
||||||
{
|
{
|
||||||
guint w = write_idx.load ();
|
size_t w = write_idx.load ();
|
||||||
const guint free_cnt = write_space ();
|
const size_t free_cnt = write_space ();
|
||||||
|
|
||||||
if (free_cnt == 0) {
|
if (free_cnt == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const guint to_write = cnt > free_cnt ? free_cnt : cnt;
|
const size_t to_write = cnt > free_cnt ? free_cnt : cnt;
|
||||||
const guint cnt2 = w + to_write;
|
const size_t cnt2 = w + to_write;
|
||||||
|
|
||||||
guint n1, n2;
|
size_t n1, n2;
|
||||||
if (cnt2 > size) {
|
if (cnt2 > size) {
|
||||||
n1 = size - w;
|
n1 = size - w;
|
||||||
n2 = cnt2 & size_mask;
|
n2 = cnt2 & size_mask;
|
||||||
|
|
@ -281,8 +281,8 @@ PlaybackBuffer<T>::write_zero (guint cnt)
|
||||||
return to_write;
|
return to_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> /*LIBPBD_API*/ guint
|
template<class T> /*LIBPBD_API*/ size_t
|
||||||
PlaybackBuffer<T>::read (T *dest, guint cnt, bool commit, guint offset)
|
PlaybackBuffer<T>::read (T *dest, size_t cnt, bool commit, size_t offset)
|
||||||
{
|
{
|
||||||
Glib::Threads::Mutex::Lock lm (_reset_lock, Glib::Threads::TRY_LOCK);
|
Glib::Threads::Mutex::Lock lm (_reset_lock, Glib::Threads::TRY_LOCK);
|
||||||
if (!lm.locked ()) {
|
if (!lm.locked ()) {
|
||||||
|
|
@ -290,10 +290,10 @@ PlaybackBuffer<T>::read (T *dest, guint cnt, bool commit, guint offset)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint r = read_idx.load ();
|
size_t r = read_idx.load ();
|
||||||
const guint w = write_idx.load ();
|
const size_t w = write_idx.load ();
|
||||||
|
|
||||||
guint free_cnt = (w > r) ? (w - r) : ((w - r + size) & size_mask);
|
size_t free_cnt = (w > r) ? (w - r) : ((w - r + size) & size_mask);
|
||||||
|
|
||||||
if (!commit && offset > 0) {
|
if (!commit && offset > 0) {
|
||||||
if (offset > free_cnt) {
|
if (offset > free_cnt) {
|
||||||
|
|
@ -303,11 +303,11 @@ PlaybackBuffer<T>::read (T *dest, guint cnt, bool commit, guint offset)
|
||||||
r = (r + offset) & size_mask;
|
r = (r + offset) & size_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
const guint to_read = cnt > free_cnt ? free_cnt : cnt;
|
const size_t to_read = cnt > free_cnt ? free_cnt : cnt;
|
||||||
|
|
||||||
const guint cnt2 = r + to_read;
|
const size_t cnt2 = r + to_read;
|
||||||
|
|
||||||
guint n1, n2;
|
size_t n1, n2;
|
||||||
if (cnt2 > size) {
|
if (cnt2 > size) {
|
||||||
n1 = size - r;
|
n1 = size - r;
|
||||||
n2 = cnt2 & size_mask;
|
n2 = cnt2 & size_mask;
|
||||||
|
|
@ -327,7 +327,7 @@ PlaybackBuffer<T>::read (T *dest, guint cnt, bool commit, guint offset)
|
||||||
if (commit) {
|
if (commit) {
|
||||||
SpinLock sl (_reservation_lock);
|
SpinLock sl (_reservation_lock);
|
||||||
read_idx.store (r);
|
read_idx.store (r);
|
||||||
g_atomic_int_set (&reserved, std::min (reservation, reserved.load () + to_read));
|
reserved.store (std::min (reservation, reserved.load () + to_read));
|
||||||
}
|
}
|
||||||
return to_read;
|
return to_read;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,15 +72,15 @@ class /*LIBPBD_API*/ RingBufferNPT
|
||||||
void get_write_vector (rw_vector *);
|
void get_write_vector (rw_vector *);
|
||||||
|
|
||||||
void decrement_read_ptr (size_t cnt) {
|
void decrement_read_ptr (size_t cnt) {
|
||||||
g_atomic_int_set (&read_ptr, (read_ptr.load () - cnt) % size);
|
read_ptr.store ((read_ptr.load () - cnt) % size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void increment_read_ptr (size_t cnt) {
|
void increment_read_ptr (size_t cnt) {
|
||||||
g_atomic_int_set (&read_ptr, (read_ptr.load () + cnt) % size);
|
read_ptr.store ((read_ptr.load () + cnt) % size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void increment_write_ptr (size_t cnt) {
|
void increment_write_ptr (size_t cnt) {
|
||||||
g_atomic_int_set (&write_ptr, (write_ptr.load () + cnt) % size);
|
write_ptr.store ((write_ptr.load () + cnt) % size);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write_space () {
|
size_t write_space () {
|
||||||
|
|
@ -161,7 +161,7 @@ RingBufferNPT<T>::read (T *dest, size_t cnt)
|
||||||
priv_read_ptr = n2;
|
priv_read_ptr = n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_atomic_int_set (&read_ptr, priv_read_ptr);
|
read_ptr.store (priv_read_ptr);
|
||||||
return to_read;
|
return to_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,7 +200,7 @@ RingBufferNPT<T>::write (const T *src, size_t cnt)
|
||||||
priv_write_ptr = n2;
|
priv_write_ptr = n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_atomic_int_set (&write_ptr, priv_write_ptr);
|
write_ptr.store (priv_write_ptr);
|
||||||
return to_write;
|
return to_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ class LIBPBD_API Stateful {
|
||||||
virtual void suspend_property_changes ();
|
virtual void suspend_property_changes ();
|
||||||
virtual void resume_property_changes ();
|
virtual void resume_property_changes ();
|
||||||
|
|
||||||
bool property_changes_suspended() const { return g_atomic_int_get (const_cast<std::atomic<int>*> (&_stateful_frozen)) > 0; }
|
bool property_changes_suspended() const { return _stateful_frozen.load() > 0; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue