Rewrite comments about exception safety guarantees with Doxygen...
... Defining a new macro, which generates a special paragraph with links to a new page describing the principles.
This commit is contained in:
parent
0e10a27172
commit
372393f49e
10
audacity.dox
10
audacity.dox
|
@ -2465,3 +2465,13 @@ GENERATE_LEGEND = YES
|
|||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
# More aliases
|
||||
|
||||
# @excsafety
|
||||
# Example usage:
|
||||
# "@excsafety{Strong} -- Leaves @c *this unchanged in case of exceptions"
|
||||
# Argument may be Weak, Partial, Strong, No-fail, Mixed
|
||||
# Generates a special paragraph with a link to a page section explaining the
|
||||
# exception safety level
|
||||
ALIASES += excsafety{1}="@par Exception safety guarantee:^^@ref \1-guarantee \"\1\""
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*!
|
||||
@page exception-safety Exception safety guarantees
|
||||
@brief Principles of robust error recovery
|
||||
@tableofcontents
|
||||
|
||||
@section Weak-guarantee Weak guarantee
|
||||
|
||||
An operation providing a weak guarantee ensures that in case of errors
|
||||
or exceptions, related objects remain in a consistent, but
|
||||
unspecified, state. What constitutes "consistency" varies but at
|
||||
minimum, each object can be safety destroyed or reassigned.
|
||||
|
||||
A collection of cooperating objects, each providing a
|
||||
@ref Strong-guarantee "strong" guarantee for all of its methods, might only
|
||||
implement a weak guarantee for the higher level of organization.
|
||||
|
||||
@section Partial-guarantee Partial guarantee
|
||||
|
||||
Intermediate between @ref Strong-guarantee "strong" and
|
||||
@ref Weak-guarantee "weak", an operation may guarantee in case of errors
|
||||
and exceptions some less than total degree of preservation of prior
|
||||
data against loss, described in documentation comments.
|
||||
|
||||
@section Strong-guarantee Strong guarantee
|
||||
|
||||
An operation providing a strong guarantee ensures that in case of
|
||||
errors or exceptions, all related objects remain in the same state as
|
||||
they were in at the beginning.
|
||||
|
||||
"Same" might refer only to logical
|
||||
contents, not necessarily bitwise, physical identity.
|
||||
|
||||
This is not the strongest guarantee -- that would be
|
||||
@ref No-fail-guarantee "no-fail".
|
||||
|
||||
@subsection Strong-guarantee-compound Strong guarantee for compound operations
|
||||
|
||||
To reassign a complex object with a strong exception safety guarantee,
|
||||
the copy-and-swap C++ idiom is often used:
|
||||
|
||||
- A temporary copy is built, risking exceptions at multiple places.
|
||||
|
||||
- If a later stage of this construction fails,
|
||||
@ref No-throw-guarantee "no-throw" destructors for the
|
||||
earlier stages are invoked to reclaim resources allocated to the
|
||||
partial object.
|
||||
|
||||
- Only after all possibility of exceptions, a @ref No-throw-guarantee
|
||||
"no-throw" swap changes the contents of @c *this.
|
||||
|
||||
- The @ref No-throw-guarantee "no-throw" destructor of the temporary destroys
|
||||
the old contents.
|
||||
|
||||
If the swap is never reached, then the contents of @c *this are left
|
||||
unchanged.
|
||||
|
||||
What is described next can be seen as a generalization of that idiom.
|
||||
To provide a strong guarantee of a compound operation, another common
|
||||
pattern is this:
|
||||
|
||||
-# for each step, implement a separate strong guarantee in case of
|
||||
failure,
|
||||
|
||||
-# for each step (except perhaps the last), implement a
|
||||
@ref No-fail-guarantee "no-fail" rollback operation that can undo it even
|
||||
after success,
|
||||
|
||||
-# initialize a variable, typically called @c success or @c committed,
|
||||
to @c false,
|
||||
|
||||
-# write one or more @ref finally blocks that invoke the rollbacks if the
|
||||
variable remains false,
|
||||
|
||||
-# invoke the sequence of fallible, strongly guaranteed steps,
|
||||
|
||||
-# only now, at the point of assured success, set the variable to
|
||||
@c true, so that the @ref finally blocks do nothing, and invoke other
|
||||
finalization steps, which must be
|
||||
@ref No-fail-guarantee "no-fail".
|
||||
|
||||
Steps 4 and 5 might interleave, but it is very important to order all
|
||||
of step 5 before all of step 6.
|
||||
|
||||
@section No-throw-guarantee No-throw guarantee
|
||||
|
||||
An operation providing a no-throw guarantee will never allow an
|
||||
exception to escape, unless for certain conditions such as memory
|
||||
exhaustion that the program treats as absolutely unrecoverable.
|
||||
|
||||
This guarantee refers only to the programming language technicality of
|
||||
exception propagation, and is not the same as the stronger
|
||||
@ref No-fail-guarantee "No-fail" guarantee.
|
||||
|
||||
This is almost always a requirement for a C++ destructor. This
|
||||
includes a lambda as argument to the function template @ref finally,
|
||||
which generates an ad hoc destructor.
|
||||
|
||||
If a class has a swap operation, that too should be no-throw.
|
||||
|
||||
@section No-fail-guarantee No-fail guarantee
|
||||
|
||||
An operation providing a no-fail guarantee will never indicate failure
|
||||
by any means, whether that be an error return code or an escaping
|
||||
exception. It will succeed unless in case of absolutely unrecoverable
|
||||
contingencies such as memory exhaustion or power failure.
|
||||
|
||||
No-fail guarantees are often necessary in functions that perform a
|
||||
final phase commit of a collection of related changes or that perform
|
||||
rollbacks of unsuccessful changes -- whether for a database in the
|
||||
strict sense or analogously.
|
||||
|
||||
@section Mixed-guarantee Mixed guarantees
|
||||
|
||||
Some operations may provide a mix of guarantees: such as, that some
|
||||
condition will hold without fail whether the operation finishes
|
||||
normally or exceptionally; yet, only weak or strong guarantees are
|
||||
given with respect to other conditions. Documentation comments should
|
||||
describe details.
|
||||
|
||||
*/
|
|
@ -2365,8 +2365,8 @@ void AudioIO::StopStream()
|
|||
GuardedCall( [&] {
|
||||
WaveTrack* track = mCaptureTracks[i].get();
|
||||
|
||||
// use NOFAIL-GUARANTEE that track is flushed,
|
||||
// PARTIAL-GUARANTEE that some initial length of the recording
|
||||
// use No-fail-guarantee that track is flushed,
|
||||
// Partial-guarantee that some initial length of the recording
|
||||
// is saved.
|
||||
// See comments in FillBuffers().
|
||||
track->Flush();
|
||||
|
|
|
@ -371,8 +371,8 @@ void Envelope::Insert(double when, double value)
|
|||
mEnv.push_back( EnvPoint{ when, value });
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void Envelope::CollapseRegion( double t0, double t1, double sampleDur )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
if ( t1 <= t0 )
|
||||
return;
|
||||
|
@ -459,8 +459,8 @@ void Envelope::CollapseRegion( double t0, double t1, double sampleDur )
|
|||
// envelope point applies to the first sample, but the t=tracklen
|
||||
// envelope point applies one-past the last actual sample.
|
||||
// t0 should be in the domain of this; if not, it is trimmed.
|
||||
/*! @excsafety{No-fail} */
|
||||
void Envelope::PasteEnvelope( double t0, const Envelope *e, double sampleDur )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
const bool wasEmpty = (this->mEnv.size() == 0);
|
||||
auto otherSize = e->mEnv.size();
|
||||
|
@ -542,9 +542,9 @@ void Envelope::PasteEnvelope( double t0, const Envelope *e, double sampleDur )
|
|||
ConsistencyCheck();
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void Envelope::RemoveUnneededPoints
|
||||
( size_t startAt, bool rightward, bool testNeighbors )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
// startAt is the index of a recently inserted point which might make no
|
||||
// difference in envelope evaluation, or else might cause nearby points to
|
||||
|
@ -608,9 +608,9 @@ void Envelope::RemoveUnneededPoints
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
std::pair< int, int > Envelope::ExpandRegion
|
||||
( double t0, double tlen, double *pLeftVal, double *pRightVal )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
// t0 is relative time
|
||||
|
||||
|
@ -659,8 +659,8 @@ std::pair< int, int > Envelope::ExpandRegion
|
|||
return { 1 + range.first, index };
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void Envelope::InsertSpace( double t0, double tlen )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
auto range = ExpandRegion( t0 - mOffset, tlen, nullptr, nullptr );
|
||||
|
||||
|
@ -780,14 +780,14 @@ std::pair<int, int> Envelope::EqualRange( double when, double sampleDur ) const
|
|||
|
||||
// Control
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void Envelope::SetOffset(double newOffset)
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
mOffset = newOffset;
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void Envelope::SetTrackLen( double trackLen, double sampleDur )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
// Preserve the left-side limit at trackLen.
|
||||
auto range = EqualRange( trackLen, sampleDur );
|
||||
|
@ -807,8 +807,8 @@ void Envelope::SetTrackLen( double trackLen, double sampleDur )
|
|||
AddPointAtEnd( mTrackLen, value );
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void Envelope::RescaleTimes( double newLength )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
if ( mTrackLen == 0 ) {
|
||||
for ( auto &point : mEnv )
|
||||
|
|
|
@ -12,4 +12,8 @@
|
|||
|
||||
class wxFileName;
|
||||
|
||||
//! Update Audacity 1.0 file in-place to XML format
|
||||
/*! @return true if successful, else no effect on the file
|
||||
@excsafety{Strong}
|
||||
*/
|
||||
bool ConvertLegacyProjectFile(const wxFileName &filename);
|
||||
|
|
|
@ -94,12 +94,12 @@ auto ProjectAudioManager::StatusWidthFunction(
|
|||
return {};
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} -- For state of mCutPreviewTracks */
|
||||
int ProjectAudioManager::PlayPlayRegion(const SelectedRegion &selectedRegion,
|
||||
const AudioIOStartStreamOptions &options,
|
||||
PlayMode mode,
|
||||
bool backwards, /* = false */
|
||||
bool playWhiteSpace /* = false */)
|
||||
// STRONG-GUARANTEE (for state of mCutPreviewTracks)
|
||||
{
|
||||
auto &projectAudioManager = *this;
|
||||
bool canStop = projectAudioManager.CanStopAudioStream();
|
||||
|
@ -458,8 +458,8 @@ WaveTrackArray ProjectAudioManager::ChooseExistingRecordingTracks(
|
|||
return {};
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} -- For state of current project's tracks */
|
||||
void ProjectAudioManager::OnRecord(bool altAppearance)
|
||||
// STRONG-GUARANTEE (for state of current project's tracks)
|
||||
{
|
||||
bool bPreferNewTrack;
|
||||
gPrefs->Read("/GUI/PreferNewTrackRecord", &bPreferNewTrack, false);
|
||||
|
@ -803,10 +803,10 @@ void ProjectAudioManager::OnPause()
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} -- For state of mCutPreviewTracks*/
|
||||
void ProjectAudioManager::SetupCutPreviewTracks(double WXUNUSED(playStart), double cutStart,
|
||||
double cutEnd, double WXUNUSED(playEnd))
|
||||
|
||||
// STRONG-GUARANTEE (for state of mCutPreviewTracks)
|
||||
{
|
||||
ClearCutPreviewTracks();
|
||||
AudacityProject *p = &mProject;
|
||||
|
@ -822,7 +822,7 @@ void ProjectAudioManager::SetupCutPreviewTracks(double WXUNUSED(playStart), doub
|
|||
newTrack->Clear(cutStart, cutEnd);
|
||||
cutPreviewTracks->Add( newTrack );
|
||||
}
|
||||
// use NOTHROW-GUARANTEE:
|
||||
// use No-throw-guarantee:
|
||||
mCutPreviewTracks = cutPreviewTracks;
|
||||
}
|
||||
}
|
||||
|
@ -879,7 +879,7 @@ void ProjectAudioManager::OnAudioIOStopRecording()
|
|||
}
|
||||
else {
|
||||
// Add to history
|
||||
// We want this to have NOFAIL-GUARANTEE if we get here from exception
|
||||
// We want this to have No-fail-guarantee if we get here from exception
|
||||
// handling of recording, and that means we rely on the last autosave
|
||||
// successully committed to the database, not risking a failure
|
||||
history.PushState(XO("Recorded Audio"), XO("Record"),
|
||||
|
|
|
@ -132,8 +132,8 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
bool Sequence::ConvertToSampleFormat(sampleFormat format)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
if (format == mSampleFormat)
|
||||
// no change
|
||||
|
@ -467,8 +467,8 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
if ((s < 0) || (s > mNumSamples))
|
||||
{
|
||||
|
@ -568,10 +568,10 @@ void Sequence::Paste(sampleCount s, const Sequence *src)
|
|||
largerBlockLen.as_size_t(),
|
||||
mSampleFormat);
|
||||
|
||||
// Don't make a duplicate array. We can still give STRONG-GUARANTEE
|
||||
// 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
|
||||
// use No-fail-guarantee in remaining steps
|
||||
for (unsigned int i = b + 1; i < numBlocks; i++)
|
||||
mBlock[i].start += addedLen;
|
||||
|
||||
|
@ -668,14 +668,14 @@ void Sequence::Paste(sampleCount s, const Sequence *src)
|
|||
(newBlock, mNumSamples + addedLen, wxT("Paste branch three"));
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void Sequence::SetSilence(sampleCount s0, sampleCount len)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
SetSamples(NULL, mSampleFormat, s0, len);
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void Sequence::InsertSilence(sampleCount s0, sampleCount len)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
auto &factory = *mpFactory;
|
||||
|
||||
|
@ -720,7 +720,7 @@ void Sequence::InsertSilence(sampleCount s0, sampleCount len)
|
|||
|
||||
sTrack.mNumSamples = pos;
|
||||
|
||||
// use STRONG-GUARANTEE
|
||||
// use Strong-guarantee
|
||||
Paste(s0, &sTrack);
|
||||
}
|
||||
|
||||
|
@ -1104,9 +1104,9 @@ bool Sequence::Get(int b, samplePtr buffer, sampleFormat format,
|
|||
}
|
||||
|
||||
// Pass NULL to set silence
|
||||
/*! @excsafety{Strong} */
|
||||
void Sequence::SetSamples(samplePtr buffer, sampleFormat format,
|
||||
sampleCount start, sampleCount len)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
auto &factory = *mpFactory;
|
||||
|
||||
|
@ -1470,8 +1470,8 @@ size_t Sequence::GetIdealAppendLen() const
|
|||
return max - lastBlockLen;
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void Sequence::Append(samplePtr buffer, sampleFormat format, size_t len)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
if (len == 0)
|
||||
return;
|
||||
|
@ -1577,8 +1577,8 @@ void Sequence::Blockify(SampleBlockFactory &factory,
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void Sequence::Delete(sampleCount start, sampleCount len)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
if (len == 0)
|
||||
return;
|
||||
|
@ -1631,10 +1631,10 @@ void Sequence::Delete(sampleCount start, sampleCount len)
|
|||
|
||||
b.sb = factory.Create(scratch.ptr(), newLen, mSampleFormat);
|
||||
|
||||
// Don't make a duplicate array. We can still give STRONG-GUARANTEE
|
||||
// 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
|
||||
// use No-fail-guarantee in remaining steps
|
||||
|
||||
for (unsigned int j = b0 + 1; j < numBlocks; j++)
|
||||
mBlock[j].start -= len;
|
||||
|
@ -1814,7 +1814,7 @@ void Sequence::CommitChangesIfConsistent
|
|||
ConsistencyCheck( newBlock, mMaxSamples, 0, numSamples, whereStr ); // may throw
|
||||
|
||||
// now commit
|
||||
// use NOFAIL-GUARANTEE
|
||||
// use No-fail-guarantee
|
||||
|
||||
mBlock.swap(newBlock);
|
||||
mNumSamples = numSamples;
|
||||
|
@ -1857,7 +1857,7 @@ void Sequence::AppendBlocksIfConsistent
|
|||
ConsistencyCheck( mBlock, mMaxSamples, prevSize, numSamples, whereStr ); // may throw
|
||||
|
||||
// now commit
|
||||
// use NOFAIL-GUARANTEE
|
||||
// use No-fail-guarantee
|
||||
|
||||
mNumSamples = numSamples;
|
||||
consistent = true;
|
||||
|
|
|
@ -1073,8 +1073,8 @@ void TrackList::UpdatePendingTracks()
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void TrackList::ClearPendingTracks( ListOfTracks *pAdded )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
for (const auto &pTrack: mPendingUpdates)
|
||||
pTrack->SetOwner( {}, {} );
|
||||
|
@ -1115,6 +1115,7 @@ void TrackList::ClearPendingTracks( ListOfTracks *pAdded )
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
bool TrackList::ApplyPendingTracks()
|
||||
{
|
||||
bool result = false;
|
||||
|
@ -1128,8 +1129,8 @@ bool TrackList::ApplyPendingTracks()
|
|||
updates.swap( mPendingUpdates );
|
||||
}
|
||||
|
||||
// Remaining steps must be NOFAIL-GUARANTEE so that this function
|
||||
// gives STRONG-GUARANTEE
|
||||
// Remaining steps must be No-fail-guarantee so that this function
|
||||
// gives Strong-guarantee
|
||||
|
||||
std::vector< std::shared_ptr<Track> > reinstated;
|
||||
|
||||
|
|
|
@ -211,8 +211,8 @@ WaveClip::~WaveClip()
|
|||
{
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void WaveClip::SetOffset(double offset)
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
mOffset = offset;
|
||||
mEnvelope->SetOffset(mOffset);
|
||||
|
@ -224,14 +224,14 @@ bool WaveClip::GetSamples(samplePtr buffer, sampleFormat format,
|
|||
return mSequence->Get(buffer, format, start, len, mayThrow);
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveClip::SetSamples(samplePtr buffer, sampleFormat format,
|
||||
sampleCount start, size_t len)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
// use STRONG-GUARANTEE
|
||||
// use Strong-guarantee
|
||||
mSequence->SetSamples(buffer, format, start, len);
|
||||
|
||||
// use NOFAIL-GUARANTEE
|
||||
// use No-fail-guarantee
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
|
@ -1169,8 +1169,8 @@ void WaveClip::ConvertToSampleFormat(sampleFormat format)
|
|||
MarkChanged();
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void WaveClip::UpdateEnvelopeTrackLen()
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
mEnvelope->SetTrackLen
|
||||
((mSequence->GetNumSamples().as_double()) / mRate, 1.0 / GetRate());
|
||||
|
@ -1202,11 +1202,11 @@ void WaveClip::GetDisplayRect(wxRect* r)
|
|||
*r = mDisplayRect;
|
||||
}
|
||||
|
||||
/*! @excsafety{Partial}
|
||||
-- Some prefix (maybe none) of the buffer is appended,
|
||||
and no content already flushed to disk is lost. */
|
||||
bool WaveClip::Append(samplePtr buffer, sampleFormat format,
|
||||
size_t len, unsigned int stride /* = 1 */)
|
||||
// PARTIAL-GUARANTEE in case of exceptions:
|
||||
// Some prefix (maybe none) of the buffer is appended, and no content already
|
||||
// flushed to disk is lost.
|
||||
{
|
||||
//wxLogDebug(wxT("Append: len=%lli"), (long long) len);
|
||||
bool result = false;
|
||||
|
@ -1219,7 +1219,7 @@ bool WaveClip::Append(samplePtr buffer, sampleFormat format,
|
|||
mAppendBuffer.Allocate(maxBlockSize, seqFormat);
|
||||
|
||||
auto cleanup = finally( [&] {
|
||||
// use NOFAIL-GUARANTEE
|
||||
// use No-fail-guarantee
|
||||
UpdateEnvelopeTrackLen();
|
||||
MarkChanged();
|
||||
} );
|
||||
|
@ -1227,11 +1227,11 @@ bool WaveClip::Append(samplePtr buffer, sampleFormat format,
|
|||
for(;;) {
|
||||
if (mAppendBufferLen >= blockSize) {
|
||||
// flush some previously appended contents
|
||||
// use STRONG-GUARANTEE
|
||||
// use Strong-guarantee
|
||||
mSequence->Append(mAppendBuffer.ptr(), seqFormat, blockSize);
|
||||
result = true;
|
||||
|
||||
// use NOFAIL-GUARANTEE for rest of this "if"
|
||||
// use No-fail-guarantee for rest of this "if"
|
||||
memmove(mAppendBuffer.ptr(),
|
||||
mAppendBuffer.ptr() + blockSize * SAMPLE_SIZE(seqFormat),
|
||||
(mAppendBufferLen - blockSize) * SAMPLE_SIZE(seqFormat));
|
||||
|
@ -1242,7 +1242,7 @@ bool WaveClip::Append(samplePtr buffer, sampleFormat format,
|
|||
if (len == 0)
|
||||
break;
|
||||
|
||||
// use NOFAIL-GUARANTEE for rest of this "for"
|
||||
// use No-fail-guarantee for rest of this "for"
|
||||
wxASSERT(mAppendBufferLen <= maxBlockSize);
|
||||
auto toCopy = std::min(len, maxBlockSize - mAppendBufferLen);
|
||||
|
||||
|
@ -1261,11 +1261,12 @@ bool WaveClip::Append(samplePtr buffer, sampleFormat format,
|
|||
return result;
|
||||
}
|
||||
|
||||
/*! @excsafety{Mixed} */
|
||||
/*! @excsafety{No-fail} -- The clip will be in a flushed state. */
|
||||
/*! @excsafety{Partial}
|
||||
-- Some initial portion (maybe none) of the append buffer of the
|
||||
clip gets appended; no previously flushed contents are lost. */
|
||||
void WaveClip::Flush()
|
||||
// NOFAIL-GUARANTEE that the clip will be in a flushed state.
|
||||
// PARTIAL-GUARANTEE in case of exceptions:
|
||||
// Some initial portion (maybe none) of the append buffer of the
|
||||
// clip gets appended; no previously flushed contents are lost.
|
||||
{
|
||||
//wxLogDebug(wxT("WaveClip::Flush"));
|
||||
//wxLogDebug(wxT(" mAppendBufferLen=%lli"), (long long) mAppendBufferLen);
|
||||
|
@ -1277,7 +1278,7 @@ void WaveClip::Flush()
|
|||
// Blow away the append buffer even in case of failure. May lose some
|
||||
// data but don't leave the track in an un-flushed state.
|
||||
|
||||
// Use NOFAIL-GUARANTEE of these steps.
|
||||
// Use No-fail-guarantee of these steps.
|
||||
mAppendBufferLen = 0;
|
||||
UpdateEnvelopeTrackLen();
|
||||
MarkChanged();
|
||||
|
@ -1366,8 +1367,8 @@ void WaveClip::WriteXML(XMLWriter &xmlFile) const
|
|||
xmlFile.EndTag(wxT("waveclip"));
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveClip::Paste(double t0, const WaveClip* other)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
const bool clipNeedsResampling = other->mRate != mRate;
|
||||
const bool clipNeedsNewFormat =
|
||||
|
@ -1409,10 +1410,10 @@ void WaveClip::Paste(double t0, const WaveClip* other)
|
|||
sampleCount s0;
|
||||
TimeToSamplesClip(t0, &s0);
|
||||
|
||||
// Assume STRONG-GUARANTEE from Sequence::Paste
|
||||
// Assume Strong-guarantee from Sequence::Paste
|
||||
mSequence->Paste(s0, pastedClip->mSequence.get());
|
||||
|
||||
// Assume NOFAIL-GUARANTEE in the remaining
|
||||
// Assume No-fail-guarantee in the remaining
|
||||
MarkChanged();
|
||||
auto sampleTime = 1.0 / GetRate();
|
||||
mEnvelope->PasteEnvelope
|
||||
|
@ -1423,17 +1424,17 @@ void WaveClip::Paste(double t0, const WaveClip* other)
|
|||
mCutLines.push_back(std::move(holder));
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveClip::InsertSilence( double t, double len, double *pEnvelopeValue )
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
sampleCount s0;
|
||||
TimeToSamplesClip(t, &s0);
|
||||
auto slen = (sampleCount)floor(len * mRate + 0.5);
|
||||
|
||||
// use STRONG-GUARANTEE
|
||||
// use Strong-guarantee
|
||||
GetSequence()->InsertSilence(s0, slen);
|
||||
|
||||
// use NOFAIL-GUARANTEE
|
||||
// use No-fail-guarantee
|
||||
OffsetCutLines(t, len);
|
||||
|
||||
const auto sampleTime = 1.0 / GetRate();
|
||||
|
@ -1456,25 +1457,25 @@ void WaveClip::InsertSilence( double t, double len, double *pEnvelopeValue )
|
|||
MarkChanged();
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveClip::AppendSilence( double len, double envelopeValue )
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
auto t = GetEndTime();
|
||||
InsertSilence( t, len, &envelopeValue );
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveClip::Clear(double t0, double t1)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
sampleCount s0, s1;
|
||||
|
||||
TimeToSamplesClip(t0, &s0);
|
||||
TimeToSamplesClip(t1, &s1);
|
||||
|
||||
// use STRONG-GUARANTEE
|
||||
// use Strong-guarantee
|
||||
GetSequence()->Delete(s0, s1-s0);
|
||||
|
||||
// use NOFAIL-GUARANTEE in the remaining
|
||||
// use No-fail-guarantee in the remaining
|
||||
|
||||
// msmeyer
|
||||
//
|
||||
|
@ -1524,10 +1525,10 @@ void WaveClip::Clear(double t0, double t1)
|
|||
MarkChanged();
|
||||
}
|
||||
|
||||
/*! @excsafety{Weak}
|
||||
-- This WaveClip remains destructible in case of AudacityException.
|
||||
But some cutlines may be deleted */
|
||||
void WaveClip::ClearAndAddCutLine(double t0, double t1)
|
||||
// WEAK-GUARANTEE
|
||||
// this WaveClip remains destructible in case of AudacityException.
|
||||
// But some cutlines may be deleted
|
||||
{
|
||||
if (t0 > GetEndTime() || t1 < GetStartTime())
|
||||
return; // time out of bounds
|
||||
|
@ -1565,7 +1566,7 @@ void WaveClip::ClearAndAddCutLine(double t0, double t1)
|
|||
TimeToSamplesClip(t0, &s0);
|
||||
TimeToSamplesClip(t1, &s1);
|
||||
|
||||
// use WEAK-GUARANTEE
|
||||
// use Weak-guarantee
|
||||
GetSequence()->Delete(s0, s1-s0);
|
||||
|
||||
// Collapse envelope
|
||||
|
@ -1598,8 +1599,8 @@ bool WaveClip::FindCutLine(double cutLinePosition,
|
|||
return false;
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveClip::ExpandCutLine(double cutLinePosition)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
auto end = mCutLines.end();
|
||||
auto it = std::find_if( mCutLines.begin(), end,
|
||||
|
@ -1609,7 +1610,7 @@ void WaveClip::ExpandCutLine(double cutLinePosition)
|
|||
|
||||
if ( it != end ) {
|
||||
auto cutline = it->get();
|
||||
// assume STRONG-GUARANTEE from Paste
|
||||
// assume Strong-guarantee from Paste
|
||||
|
||||
// Envelope::Paste takes offset into account, WaveClip::Paste doesn't!
|
||||
// Do this to get the right result:
|
||||
|
@ -1646,8 +1647,8 @@ bool WaveClip::RemoveCutLine(double cutLinePosition)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void WaveClip::OffsetCutLines(double t0, double len)
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
for (const auto &cutLine : mCutLines)
|
||||
{
|
||||
|
@ -1671,8 +1672,8 @@ void WaveClip::SetRate(int rate)
|
|||
MarkChanged();
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveClip::Resample(int rate, ProgressDialog *progress)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
// Note: it is not necessary to do this recursively to cutlines.
|
||||
// They get resampled as needed when they are expanded.
|
||||
|
@ -1744,7 +1745,7 @@ void WaveClip::Resample(int rate, ProgressDialog *progress)
|
|||
};
|
||||
else
|
||||
{
|
||||
// Use NOFAIL-GUARANTEE in these steps
|
||||
// Use No-fail-guarantee in these steps
|
||||
|
||||
// Invalidate wave display cache
|
||||
mWaveCache = std::make_unique<WaveCache>();
|
||||
|
|
|
@ -216,7 +216,8 @@ public:
|
|||
int GetColourIndex( ) const { return mColourIndex;};
|
||||
void SetOffset(double offset);
|
||||
double GetOffset() const { return mOffset; }
|
||||
void Offset(double delta) // NOFAIL-GUARANTEE
|
||||
/*! @excsafety{No-fail} */
|
||||
void Offset(double delta)
|
||||
{ SetOffset(GetOffset() + delta); }
|
||||
double GetStartTime() const;
|
||||
double GetEndTime() const;
|
||||
|
@ -251,7 +252,8 @@ public:
|
|||
/** WaveTrack calls this whenever data in the wave clip changes. It is
|
||||
* called automatically when WaveClip has a chance to know that something
|
||||
* has changed, like when member functions SetSamples() etc. are called. */
|
||||
void MarkChanged() // NOFAIL-GUARANTEE
|
||||
/*! @excsafety{No-fail} */
|
||||
void MarkChanged()
|
||||
{ mDirty++; }
|
||||
|
||||
/** Getting high-level data for screen display and clipping
|
||||
|
|
|
@ -209,13 +209,13 @@ double WaveTrack::GetOffset() const
|
|||
return GetStartTime();
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
void WaveTrack::SetOffset(double o)
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
double delta = o - GetOffset();
|
||||
|
||||
for (const auto &clip : mClips)
|
||||
// assume NOFAIL-GUARANTEE
|
||||
// assume No-fail-guarantee
|
||||
clip->SetOffset(clip->GetOffset() + delta);
|
||||
|
||||
mOffset = o;
|
||||
|
@ -404,8 +404,8 @@ void WaveTrack::SetOldChannelGain(int channel, float gain)
|
|||
|
||||
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveTrack::SetWaveColorIndex(int colorIndex)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
for (const auto &clip : mClips)
|
||||
clip->SetColourIndex( colorIndex );
|
||||
|
@ -413,9 +413,8 @@ void WaveTrack::SetWaveColorIndex(int colorIndex)
|
|||
}
|
||||
|
||||
|
||||
/*! @excsafety{Weak} -- Might complete on only some clips */
|
||||
void WaveTrack::ConvertToSampleFormat(sampleFormat format)
|
||||
// WEAK-GUARANTEE
|
||||
// might complete on only some clips
|
||||
{
|
||||
for (const auto &clip : mClips)
|
||||
clip->ConvertToSampleFormat(format);
|
||||
|
@ -456,8 +455,8 @@ Track::Holder WaveTrack::Cut(double t0, double t1)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
Track::Holder WaveTrack::SplitCut(double t0, double t1)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
if (t1 < t0)
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
@ -489,8 +488,8 @@ Track::Holder WaveTrack::CutAndAddCutLine(double t0, double t1)
|
|||
|
||||
//Trim trims within a clip, rather than trimming everything.
|
||||
//If a bound is outside a clip, it trims everything.
|
||||
/*! @excsafety{Weak} */
|
||||
void WaveTrack::Trim (double t0, double t1)
|
||||
// WEAK-GUARANTEE
|
||||
{
|
||||
bool inside0 = false;
|
||||
bool inside1 = false;
|
||||
|
@ -611,14 +610,14 @@ Track::Holder WaveTrack::CopyNonconst(double t0, double t1)
|
|||
return Copy(t0, t1);
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveTrack::Clear(double t0, double t1)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
HandleClear(t0, t1, false, false);
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveTrack::ClearAndAddCutLine(double t0, double t1)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
HandleClear(t0, t1, true, false);
|
||||
}
|
||||
|
@ -715,6 +714,8 @@ void WaveTrack::SetWaveformSettings(std::unique_ptr<WaveformSettings> &&pSetting
|
|||
// be pasted with visible split lines. Normally, effects do not
|
||||
// want these extra lines, so they may be merged out.
|
||||
//
|
||||
/*! @excsafety{Weak} -- This WaveTrack remains destructible in case of AudacityException.
|
||||
But some of its cutline clips may have been destroyed. */
|
||||
void WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
||||
double t1, // End of time to clear
|
||||
const Track *src, // What to paste
|
||||
|
@ -722,15 +723,12 @@ void WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
|||
bool merge, // Whether to remove 'extra' splits
|
||||
const TimeWarper *effectWarper // How does time change
|
||||
)
|
||||
// WEAK-GUARANTEE
|
||||
// this WaveTrack remains destructible in case of AudacityException.
|
||||
// But some of its cutline clips may have been destroyed.
|
||||
{
|
||||
double dur = std::min(t1 - t0, src->GetEndTime());
|
||||
|
||||
// If duration is 0, then it's just a plain paste
|
||||
if (dur == 0.0) {
|
||||
// use WEAK-GUARANTEE
|
||||
// use Weak-guarantee
|
||||
Paste(t0, src);
|
||||
return;
|
||||
}
|
||||
|
@ -836,7 +834,7 @@ void WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
|||
if (prev) {
|
||||
// It must be that clip is what was pasted and it begins where
|
||||
// prev ends.
|
||||
// use WEAK-GUARANTEE
|
||||
// use Weak-guarantee
|
||||
MergeClips(GetClipIndex(prev), GetClipIndex(clip));
|
||||
break;
|
||||
}
|
||||
|
@ -893,8 +891,8 @@ void WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveTrack::SplitDelete(double t0, double t1)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
bool addCutLines = false;
|
||||
bool split = true;
|
||||
|
@ -956,9 +954,9 @@ void WaveTrack::AddClip(std::shared_ptr<WaveClip> &&clip)
|
|||
mClips.push_back(std::move(clip)); // transfer ownership
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveTrack::HandleClear(double t0, double t1,
|
||||
bool addCutLines, bool split)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
if (t1 < t0)
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
@ -1067,7 +1065,7 @@ void WaveTrack::HandleClear(double t0, double t1,
|
|||
}
|
||||
|
||||
// Only now, change the contents of this track
|
||||
// use NOFAIL-GUARANTEE for the rest
|
||||
// use No-fail-guarantee for the rest
|
||||
|
||||
for (const auto &clip : mClips)
|
||||
{
|
||||
|
@ -1133,8 +1131,8 @@ void WaveTrack::SyncLockAdjust(double oldT1, double newT1)
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Weak} */
|
||||
void WaveTrack::Paste(double t0, const Track *src)
|
||||
// WEAK-GUARANTEE
|
||||
{
|
||||
bool editClipCanMove = GetEditClipsCanMove();
|
||||
|
||||
|
@ -1244,7 +1242,7 @@ void WaveTrack::Paste(double t0, const Track *src)
|
|||
if (clip->GetStartTime() > insideClip->GetStartTime() &&
|
||||
insideClip->GetEndTime() + insertDuration >
|
||||
clip->GetStartTime())
|
||||
// STRONG-GUARANTEE in case of this path
|
||||
// Strong-guarantee in case of this path
|
||||
// not that it matters.
|
||||
throw SimpleMessageBoxException{
|
||||
XO("There is not enough room available to paste the selection")
|
||||
|
@ -1264,7 +1262,7 @@ void WaveTrack::Paste(double t0, const Track *src)
|
|||
//wxPrintf("paste: multi clip mode!\n");
|
||||
|
||||
if (!editClipCanMove && !IsEmpty(t0, t0+insertDuration-1.0/mRate))
|
||||
// STRONG-GUARANTEE in case of this path
|
||||
// Strong-guarantee in case of this path
|
||||
// not that it matters.
|
||||
throw SimpleMessageBoxException{
|
||||
XO("There is not enough room available to paste the selection")
|
||||
|
@ -1325,8 +1323,8 @@ void WaveTrack::Silence(double t0, double t1)
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveTrack::InsertSilence(double t, double len)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
// Nothing to do, if length is zero.
|
||||
// Fixes Bug 1626
|
||||
|
@ -1340,7 +1338,7 @@ void WaveTrack::InsertSilence(double t, double len)
|
|||
// Special case if there is no clip yet
|
||||
auto clip = std::make_unique<WaveClip>(mpFactory, mFormat, mRate, this->GetWaveColorIndex());
|
||||
clip->InsertSilence(0, len);
|
||||
// use NOFAIL-GUARANTEE
|
||||
// use No-fail-guarantee
|
||||
mClips.push_back( std::move( clip ) );
|
||||
return;
|
||||
}
|
||||
|
@ -1350,11 +1348,11 @@ void WaveTrack::InsertSilence(double t, double len)
|
|||
const auto it = std::find_if( mClips.begin(), end,
|
||||
[&](const WaveClipHolder &clip) { return clip->WithinClip(t); } );
|
||||
|
||||
// use STRONG-GUARANTEE
|
||||
// use Strong-guarantee
|
||||
if (it != end)
|
||||
it->get()->InsertSilence(t, len);
|
||||
|
||||
// use NOFAIL-GUARANTEE
|
||||
// use No-fail-guarantee
|
||||
for (const auto &clip : mClips)
|
||||
{
|
||||
if (clip->BeforeClip(t))
|
||||
|
@ -1365,8 +1363,8 @@ void WaveTrack::InsertSilence(double t, double len)
|
|||
|
||||
//Performs the opposite of Join
|
||||
//Analyses selected region for possible Joined clips and disjoins them
|
||||
/*! @excsafety{Weak} */
|
||||
void WaveTrack::Disjoin(double t0, double t1)
|
||||
// WEAK-GUARANTEE
|
||||
{
|
||||
auto minSamples = TimeToLongSamples( WAVETRACK_MERGE_POINT_TOLERANCE );
|
||||
const size_t maxAtOnce = 1048576;
|
||||
|
@ -1443,8 +1441,8 @@ void WaveTrack::Disjoin(double t0, double t1)
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Weak} */
|
||||
void WaveTrack::Join(double t0, double t1)
|
||||
// WEAK-GUARANTEE
|
||||
{
|
||||
// Merge all WaveClips overlapping selection into one
|
||||
|
||||
|
@ -1497,11 +1495,11 @@ void WaveTrack::Join(double t0, double t1)
|
|||
}
|
||||
}
|
||||
|
||||
/*! @excsafety{Partial}
|
||||
-- Some prefix (maybe none) of the buffer is appended,
|
||||
and no content already flushed to disk is lost. */
|
||||
bool WaveTrack::Append(samplePtr buffer, sampleFormat format,
|
||||
size_t len, unsigned int stride /* = 1 */)
|
||||
// PARTIAL-GUARANTEE in case of exceptions:
|
||||
// Some prefix (maybe none) of the buffer is appended, and no content already
|
||||
// flushed to disk is lost.
|
||||
{
|
||||
return RightmostOrNewClip()->Append(buffer, format, len, stride);
|
||||
}
|
||||
|
@ -1562,11 +1560,12 @@ size_t WaveTrack::GetIdealBlockSize()
|
|||
return NewestOrNewClip()->GetSequence()->GetIdealBlockSize();
|
||||
}
|
||||
|
||||
/*! @excsafety{Mixed} */
|
||||
/*! @excsafety{No-fail} -- The rightmost clip will be in a flushed state. */
|
||||
/*! @excsafety{Partial}
|
||||
-- Some initial portion (maybe none) of the append buffer of the rightmost
|
||||
clip gets appended; no previously saved contents are lost. */
|
||||
void WaveTrack::Flush()
|
||||
// NOFAIL-GUARANTEE that the rightmost clip will be in a flushed state.
|
||||
// PARTIAL-GUARANTEE in case of exceptions:
|
||||
// Some initial portion (maybe none) of the append buffer of the rightmost
|
||||
// clip gets appended; no previously saved contents are lost.
|
||||
{
|
||||
// After appending, presumably. Do this to the clip that gets appended.
|
||||
RightmostOrNewClip()->Flush();
|
||||
|
@ -1929,9 +1928,9 @@ bool WaveTrack::Get(samplePtr buffer, sampleFormat format,
|
|||
return result;
|
||||
}
|
||||
|
||||
/*! @excsafety{Weak} */
|
||||
void WaveTrack::Set(samplePtr buffer, sampleFormat format,
|
||||
sampleCount start, size_t len)
|
||||
// WEAK-GUARANTEE
|
||||
{
|
||||
for (const auto &clip: mClips)
|
||||
{
|
||||
|
@ -2123,8 +2122,8 @@ WaveClip* WaveTrack::NewestOrNewClip()
|
|||
return mClips.back().get();
|
||||
}
|
||||
|
||||
/*! @excsafety{No-fail} */
|
||||
WaveClip* WaveTrack::RightmostOrNewClip()
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
if (mClips.empty()) {
|
||||
WaveClip *clip = CreateClip();
|
||||
|
@ -2252,16 +2251,16 @@ bool WaveTrack::CanInsertClip(WaveClip* clip, double &slideBy, double &toleranc
|
|||
return true;
|
||||
}
|
||||
|
||||
/*! @excsafety{Weak} */
|
||||
void WaveTrack::Split( double t0, double t1 )
|
||||
// WEAK-GUARANTEE
|
||||
{
|
||||
SplitAt( t0 );
|
||||
if( t0 != t1 )
|
||||
SplitAt( t1 );
|
||||
}
|
||||
|
||||
/*! @excsafety{Weak} */
|
||||
void WaveTrack::SplitAt(double t)
|
||||
// WEAK-GUARANTEE
|
||||
{
|
||||
for (const auto &c : mClips)
|
||||
{
|
||||
|
@ -2350,9 +2349,9 @@ void WaveTrack::UpdateLocationsCache() const
|
|||
}
|
||||
|
||||
// Expand cut line (that is, re-insert audio, then DELETE audio saved in cut line)
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveTrack::ExpandCutLine(double cutLinePosition, double* cutlineStart,
|
||||
double* cutlineEnd)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
bool editClipCanMove = GetEditClipsCanMove();
|
||||
|
||||
|
@ -2373,7 +2372,7 @@ void WaveTrack::ExpandCutLine(double cutLinePosition, double* cutlineStart,
|
|||
{
|
||||
if (clip2->GetStartTime() > clip->GetStartTime() &&
|
||||
clip->GetEndTime() + end - start > clip2->GetStartTime())
|
||||
// STRONG-GUARANTEE in case of this path
|
||||
// Strong-guarantee in case of this path
|
||||
throw SimpleMessageBoxException{
|
||||
XO("There is not enough room available to expand the cut line")
|
||||
};
|
||||
|
@ -2382,7 +2381,7 @@ void WaveTrack::ExpandCutLine(double cutLinePosition, double* cutlineStart,
|
|||
|
||||
clip->ExpandCutLine(cutLinePosition);
|
||||
|
||||
// STRONG-GUARANTEE provided that the following gives NOFAIL-GUARANTEE
|
||||
// Strong-guarantee provided that the following gives No-fail-guarantee
|
||||
|
||||
if (cutlineStart)
|
||||
*cutlineStart = start;
|
||||
|
@ -2410,8 +2409,8 @@ bool WaveTrack::RemoveCutLine(double cutLinePosition)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} */
|
||||
void WaveTrack::MergeClips(int clipidx1, int clipidx2)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
WaveClip* clip1 = GetClipByIndex(clipidx1);
|
||||
WaveClip* clip2 = GetClipByIndex(clipidx2);
|
||||
|
@ -2420,18 +2419,18 @@ void WaveTrack::MergeClips(int clipidx1, int clipidx2)
|
|||
return; // Don't throw, just do nothing.
|
||||
|
||||
// Append data from second clip to first clip
|
||||
// use STRONG-GUARANTEE
|
||||
// use Strong-guarantee
|
||||
clip1->Paste(clip1->GetEndTime(), clip2);
|
||||
|
||||
// use NOFAIL-GUARANTEE for the rest
|
||||
// use No-fail-guarantee for the rest
|
||||
// Delete second clip
|
||||
auto it = FindClip(mClips, clip2);
|
||||
mClips.erase(it);
|
||||
}
|
||||
|
||||
/*! @excsafety{Weak} -- Partial completion may leave clips at differing sample rates!
|
||||
*/
|
||||
void WaveTrack::Resample(int rate, ProgressDialog *progress)
|
||||
// WEAK-GUARANTEE
|
||||
// Partial completion may leave clips at differing sample rates!
|
||||
{
|
||||
for (const auto &clip : mClips)
|
||||
clip->Resample(rate, progress);
|
||||
|
|
|
@ -583,8 +583,8 @@ void ControlToolBar::PlayDefault()
|
|||
ProjectAudioManager::Get( mProject ).PlayCurrentRegion(looped, cutPreview);
|
||||
}
|
||||
|
||||
/*! @excsafety{Strong} -- For state of current project's tracks */
|
||||
void ControlToolBar::OnRecord(wxCommandEvent &evt)
|
||||
// STRONG-GUARANTEE (for state of current project's tracks)
|
||||
{
|
||||
// TODO: It would be neater if Menu items and Toolbar buttons used the same code for
|
||||
// enabling/disabling, and all fell into the same action routines.
|
||||
|
|
Loading…
Reference in New Issue