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:
Spekular
2020-12-29 23:01:41 +01:00
committed by GitHub
parent 67a5da8c89
commit bf7c87de7e
4 changed files with 103 additions and 3 deletions

View File

@@ -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);