mirror of
https://github.com/LMMS/lmms.git
synced 2026-05-17 11:18:30 -04:00
Fix rule of three for SampleBuffer, SampleTCO (#5727)
* Automatic formatting changes * Add copy constructor and assignemnt to SampleBuffer * Add copy constructor to SampleTCO * Delete SampleTCO copy assignment, initial work on SampleBuffer swap method * SampleBuffer: Finish(?) swap and use it for copy assignment, lock for read in copy constructor * Don't forget to unlock in copy assignment! * Formatting changes * Lock ordering in swap * Fix leak and constness Co-authored-by: Dominic Clark <mrdomclark@gmail.com> * Fix multiplication style, ensure lock is held when necessary ... by switching from an initializer list to manual assignments. * Fixes from review * Avoid more undefined behavior * Update src/tracks/SampleTrack.cpp Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
This commit is contained in:
@@ -130,6 +130,86 @@ SampleBuffer::SampleBuffer(const f_cnt_t frames)
|
||||
|
||||
|
||||
|
||||
SampleBuffer::SampleBuffer(const SampleBuffer& orig)
|
||||
{
|
||||
orig.m_varLock.lockForRead();
|
||||
|
||||
m_audioFile = orig.m_audioFile;
|
||||
m_origFrames = orig.m_origFrames;
|
||||
m_origData = (m_origFrames > 0) ? MM_ALLOC(sampleFrame, m_origFrames) : nullptr;
|
||||
m_frames = orig.m_frames;
|
||||
m_data = (m_frames > 0) ? MM_ALLOC(sampleFrame, m_frames) : nullptr;
|
||||
m_startFrame = orig.m_startFrame;
|
||||
m_endFrame = orig.m_endFrame;
|
||||
m_loopStartFrame = orig.m_loopStartFrame;
|
||||
m_loopEndFrame = orig.m_loopEndFrame;
|
||||
m_amplification = orig.m_amplification;
|
||||
m_reversed = orig.m_reversed;
|
||||
m_frequency = orig.m_frequency;
|
||||
m_sampleRate = orig.m_sampleRate;
|
||||
|
||||
//Deep copy m_origData and m_data from original
|
||||
const auto origFrameBytes = m_origFrames * BYTES_PER_FRAME;
|
||||
const auto frameBytes = m_frames * BYTES_PER_FRAME;
|
||||
if (orig.m_origData != nullptr && origFrameBytes > 0)
|
||||
{ memcpy(m_origData, orig.m_origData, origFrameBytes); }
|
||||
if (orig.m_data != nullptr && frameBytes > 0)
|
||||
{ memcpy(m_data, orig.m_data, frameBytes); }
|
||||
|
||||
orig.m_varLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void swap(SampleBuffer& first, SampleBuffer& second) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
// Lock both buffers for writing, with address as lock ordering
|
||||
if (&first == &second) { return; }
|
||||
else if (&first > &second)
|
||||
{
|
||||
first.m_varLock.lockForWrite();
|
||||
second.m_varLock.lockForWrite();
|
||||
}
|
||||
else
|
||||
{
|
||||
second.m_varLock.lockForWrite();
|
||||
first.m_varLock.lockForWrite();
|
||||
}
|
||||
|
||||
first.m_audioFile.swap(second.m_audioFile);
|
||||
swap(first.m_origData, second.m_origData);
|
||||
swap(first.m_data, second.m_data);
|
||||
swap(first.m_origFrames, second.m_origFrames);
|
||||
swap(first.m_frames, second.m_frames);
|
||||
swap(first.m_startFrame, second.m_startFrame);
|
||||
swap(first.m_endFrame, second.m_endFrame);
|
||||
swap(first.m_loopStartFrame, second.m_loopStartFrame);
|
||||
swap(first.m_loopEndFrame, second.m_loopEndFrame);
|
||||
swap(first.m_amplification, second.m_amplification);
|
||||
swap(first.m_frequency, second.m_frequency);
|
||||
swap(first.m_reversed, second.m_reversed);
|
||||
swap(first.m_sampleRate, second.m_sampleRate);
|
||||
|
||||
// Unlock again
|
||||
first.m_varLock.unlock();
|
||||
second.m_varLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SampleBuffer& SampleBuffer::operator=(SampleBuffer that)
|
||||
{
|
||||
swap(*this, that);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SampleBuffer::~SampleBuffer()
|
||||
{
|
||||
MM_FREE(m_origData);
|
||||
|
||||
Reference in New Issue
Block a user