mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-25 07:43:54 +02:00
Sequence::Paste gives strong guarantee
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user