1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-10-25 15:53:52 +02:00

Sequence::Paste gives strong guarantee

This commit is contained in:
Paul Licameli
2016-11-27 11:00:23 -05:00
parent 2ba6065961
commit 160d846643
3 changed files with 45 additions and 45 deletions

View File

@@ -72,9 +72,7 @@ Sequence::Sequence(const Sequence &orig, const std::shared_ptr<DirManager> &proj
, mMinSamples(orig.mMinSamples)
, mMaxSamples(orig.mMaxSamples)
{
bool bResult = Paste(0, &orig);
wxASSERT(bResult); // TO DO: Actually handle this.
(void)bResult;
Paste(0, &orig);
}
Sequence::~Sequence()
@@ -451,7 +449,8 @@ namespace {
}
}
bool Sequence::Paste(sampleCount s, const Sequence *src)
void Sequence::Paste(sampleCount s, const Sequence *src)
// STRONG-GUARANTEE
{
if ((s < 0) || (s > mNumSamples))
{
@@ -460,8 +459,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
// PRL: Why bother with Internat when the above is just wxT?
Internat::ToString(s.as_double(), 0).c_str(),
Internat::ToString(mNumSamples.as_double(), 0).c_str());
wxASSERT(false);
return false;
//THROW_INCONSISTENCY_EXCEPTION
;
}
// Quick check to make sure that it doesn't overflow
@@ -472,8 +471,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
// PRL: Why bother with Internat when the above is just wxT?
Internat::ToString(mNumSamples.as_double(), 0).c_str(),
Internat::ToString(src->mNumSamples.as_double(), 0).c_str());
wxASSERT(false);
return false;
//THROW_INCONSISTENCY_EXCEPTION
;
}
if (src->mSampleFormat != mSampleFormat)
@@ -481,8 +480,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
wxLogError(
wxT("Sequence::Paste: Sample format to be pasted, %s, does not match destination format, %s."),
GetSampleFormatStr(src->mSampleFormat), GetSampleFormatStr(src->mSampleFormat));
wxASSERT(false);
return false;
//THROW_INCONSISTENCY_EXCEPTION
;
}
const BlockArray &srcBlock = src->mBlock;
@@ -491,7 +490,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
auto sampleSize = SAMPLE_SIZE(mSampleFormat);
if (addedLen == 0 || srcNumBlocks == 0)
return true;
return;
const size_t numBlocks = mBlock.size();
@@ -501,12 +500,18 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
// onto the end because the current last block is longer than the
// minimum size
// Build and swap a copy so there is a strong exception safety guarantee
BlockArray newBlock{ mBlock };
sampleCount samples = mNumSamples;
for (unsigned int i = 0; i < srcNumBlocks; i++)
AppendBlock(*mDirManager, mBlock, mNumSamples, srcBlock[i]);
// AppendBlock may throw for limited disk space, if pasting from
// one project into another.
AppendBlock(*mDirManager, newBlock, samples, srcBlock[i]);
// Increase ref count or duplicate file
ConsistencyCheck(wxT("Paste branch one"));
return true;
CommitChangesIfConsistent
(newBlock, samples, wxT("Paste branch one"));
return;
}
const int b = (s == mNumSamples) ? mBlock.size() - 1 : FindBlock(s);
@@ -541,6 +546,10 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
// largerBlockLen is not more than mMaxSamples...
buffer.ptr(), largerBlockLen.as_size_t(), mSampleFormat);
// Don't make a duplicate array. We can still give STRONG-GUARANTEE
// if we modify only one block in place.
// use NOFAIL-GUARANTEE in remaining steps
block.f = file;
for (unsigned int i = b + 1; i < numBlocks; i++)
@@ -548,8 +557,10 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
mNumSamples += addedLen;
ConsistencyCheck(wxT("Paste branch two"));
return true;
// This consistency check won't throw, it asserts.
// Proof that we kept consistency is not hard.
ConsistencyCheck(wxT("Paste branch two"), false);
return;
}
// Case three: if we are inserting four or fewer blocks,
@@ -637,12 +648,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
for (i = b + 1; i < numBlocks; i++)
newBlock.push_back(mBlock[i].Plus(addedLen));
mBlock.swap(newBlock);
mNumSamples += addedLen;
ConsistencyCheck(wxT("Paste branch three"));
return true;
CommitChangesIfConsistent
(newBlock, mNumSamples + addedLen, wxT("Paste branch three"));
}
bool Sequence::SetSilence(sampleCount s0, sampleCount len)
@@ -693,11 +700,9 @@ bool Sequence::InsertSilence(sampleCount s0, sampleCount len)
sTrack.mNumSamples = pos;
bool bResult = Paste(s0, &sTrack);
wxASSERT(bResult);
Paste(s0, &sTrack);
ConsistencyCheck(wxT("InsertSilence"));
return bResult;
return true;
}
bool Sequence::AppendAlias(const wxString &fullPath,
@@ -737,13 +742,15 @@ bool Sequence::AppendCoded(const wxString &fName, sampleCount start,
return true;
}
bool Sequence::AppendBlock
void Sequence::AppendBlock
(DirManager &mDirManager,
BlockArray &mBlock, sampleCount &mNumSamples, const SeqBlock &b)
{
// Quick check to make sure that it doesn't overflow
if (Overflows((mNumSamples.as_double()) + ((double)b.f->GetLength())))
return false;
// THROW_INCONSISTENCY_EXCEPTION
return
;
SeqBlock newBlock(
mDirManager.CopyBlockFile(b.f), // Bump ref count if not locked, else copy
@@ -755,16 +762,11 @@ bool Sequence::AppendBlock
return false;
}
//Don't need to Ref because it was done by CopyBlockFile, above...
//mDirManager->Ref(newBlock.f);
mBlock.push_back(newBlock);
mNumSamples += newBlock.f->GetLength();
// Don't do a consistency check here because this
// function gets called in an inner loop.
return true;
}
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.

View File

@@ -104,7 +104,7 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
size_t len, const sampleCount *where) const;
std::unique_ptr<Sequence> Copy(sampleCount s0, sampleCount s1) const;
bool Paste(sampleCount s0, const Sequence *src);
void Paste(sampleCount s0, const Sequence *src);
size_t GetIdealAppendLen() const;
bool Append(samplePtr buffer, sampleFormat format, size_t len,
@@ -245,7 +245,7 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
int FindBlock(sampleCount pos) const;
static bool AppendBlock
static void AppendBlock
(DirManager &dirManager,
BlockArray &blocks, sampleCount &numSamples, const SeqBlock &b);

View File

@@ -1611,18 +1611,16 @@ void WaveClip::Paste(double t0, const WaveClip* other)
TimeToSamplesClip(t0, &s0);
// Assume STRONG-GUARANTEE from Sequence::Paste
if (mSequence->Paste(s0, pastedClip->mSequence.get()))
{
// Assume NOFAIL-GUARANTEE in the remaining
MarkChanged();
mEnvelope->Paste(s0.as_double()/mRate + mOffset, pastedClip->mEnvelope.get());
mEnvelope->RemoveUnneededPoints();
OffsetCutLines(t0, pastedClip->GetEndTime() - pastedClip->GetStartTime());
mSequence->Paste(s0, pastedClip->mSequence.get());
for (auto &holder : newCutlines)
mCutLines.push_back(std::move(holder));
// Assume NOFAIL-GUARANTEE in the remaining
MarkChanged();
mEnvelope->Paste(s0.as_double()/mRate + mOffset, pastedClip->mEnvelope.get());
mEnvelope->RemoveUnneededPoints();
OffsetCutLines(t0, pastedClip->GetEndTime() - pastedClip->GetStartTime());
}
for (auto &holder : newCutlines)
mCutLines.push_back(std::move(holder));
}
void WaveClip::InsertSilence(double t, double len)