mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-05 22:28:57 +02:00
OD tasks store weak pointers to block files...
... This means unneeded block files can be reclaimed sooner. This also eliminates the checks of use_count, which might vary in a multithreaded context; though that didn't really matter (because once it was below 2, the function had the only remaining shared_ptr to the block file, so it could not have increased again to 2).
This commit is contained in:
parent
aee45d9cce
commit
4744f5cc5e
@ -71,12 +71,9 @@ void ODComputeSummaryTask::DoSomeInternal()
|
|||||||
mBlockFilesMutex.Lock();
|
mBlockFilesMutex.Lock();
|
||||||
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
|
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
|
||||||
{
|
{
|
||||||
const auto &bf = mBlockFiles[0];
|
const auto bf = mBlockFiles[0].lock();
|
||||||
|
|
||||||
//first check to see if the ref count is at least 2. It should have one
|
if(bf)
|
||||||
//from when we added it to this instance's mBlockFiles array, and one from
|
|
||||||
//the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
|
|
||||||
if(bf.use_count() >= 2)
|
|
||||||
{
|
{
|
||||||
bf->DoWriteSummary();
|
bf->DoWriteSummary();
|
||||||
success = true;
|
success = true;
|
||||||
@ -85,6 +82,7 @@ void ODComputeSummaryTask::DoSomeInternal()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// The block file disappeared.
|
||||||
//the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
|
//the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
|
||||||
//because now there is less work to do.
|
//because now there is less work to do.
|
||||||
mMaxBlockFiles--;
|
mMaxBlockFiles--;
|
||||||
@ -164,7 +162,7 @@ void ODComputeSummaryTask::CalculatePercentComplete()
|
|||||||
///by default left to right, or frome the point the user has clicked.
|
///by default left to right, or frome the point the user has clicked.
|
||||||
void ODComputeSummaryTask::Update()
|
void ODComputeSummaryTask::Update()
|
||||||
{
|
{
|
||||||
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > tempBlocks;
|
std::vector< std::weak_ptr< ODPCMAliasBlockFile > > tempBlocks;
|
||||||
|
|
||||||
mWaveTrackMutex.Lock();
|
mWaveTrackMutex.Lock();
|
||||||
|
|
||||||
@ -207,10 +205,14 @@ void ODComputeSummaryTask::Update()
|
|||||||
));
|
));
|
||||||
|
|
||||||
//these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
|
//these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
|
||||||
while(insertCursor<(int)tempBlocks.size()&&
|
{
|
||||||
tempBlocks[insertCursor]->GetStart() + tempBlocks[insertCursor]->GetClipOffset() <
|
std::shared_ptr< ODPCMAliasBlockFile > ptr;
|
||||||
odpcmaFile->GetStart() + odpcmaFile->GetClipOffset())
|
while(insertCursor < (int)tempBlocks.size() &&
|
||||||
insertCursor++;
|
(!(ptr = tempBlocks[insertCursor].lock()) ||
|
||||||
|
ptr->GetStart() + ptr->GetClipOffset() <
|
||||||
|
odpcmaFile->GetStart() + odpcmaFile->GetClipOffset()))
|
||||||
|
insertCursor++;
|
||||||
|
}
|
||||||
|
|
||||||
tempBlocks.insert(tempBlocks.begin() + insertCursor++, odpcmaFile);
|
tempBlocks.insert(tempBlocks.begin() + insertCursor++, odpcmaFile);
|
||||||
}
|
}
|
||||||
@ -232,7 +234,7 @@ void ODComputeSummaryTask::Update()
|
|||||||
|
|
||||||
///Computes the summary calculation queue order of the blockfiles
|
///Computes the summary calculation queue order of the blockfiles
|
||||||
void ODComputeSummaryTask::OrderBlockFiles
|
void ODComputeSummaryTask::OrderBlockFiles
|
||||||
(std::vector< std::shared_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
|
(std::vector< std::weak_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
|
||||||
{
|
{
|
||||||
mBlockFiles.clear();
|
mBlockFiles.clear();
|
||||||
//Order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
|
//Order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
|
||||||
@ -242,27 +244,29 @@ void ODComputeSummaryTask::OrderBlockFiles
|
|||||||
|
|
||||||
//find the startpoint
|
//find the startpoint
|
||||||
auto processStartSample = GetDemandSample();
|
auto processStartSample = GetDemandSample();
|
||||||
for(int i= ((int)unorderedBlocks.size())-1;i>= 0;i--)
|
std::shared_ptr< ODPCMAliasBlockFile > firstBlock;
|
||||||
|
for(auto i = unorderedBlocks.size(); i--;)
|
||||||
{
|
{
|
||||||
//check to see if the refcount is at least two before we add it to the list.
|
auto ptr = unorderedBlocks[i].lock();
|
||||||
//There should be one Ref() from the one added by this ODTask, and one from the track.
|
if(ptr)
|
||||||
//If there isn't, then the block was deleted for some reason and we should ignore it.
|
|
||||||
if(unorderedBlocks[i].use_count() >= 2)
|
|
||||||
{
|
{
|
||||||
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
|
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
|
||||||
//and add ones that are closer.
|
//and add ones that are closer.
|
||||||
if(mBlockFiles.size() &&
|
if(firstBlock &&
|
||||||
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
|
ptr->GetGlobalEnd() >= processStartSample &&
|
||||||
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
|
( firstBlock->GetGlobalEnd() < processStartSample ||
|
||||||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart())
|
ptr->GetGlobalStart() <= firstBlock->GetGlobalStart())
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//insert at the front of the list if we get blockfiles that are after the demand sample
|
//insert at the front of the list if we get blockfiles that are after the demand sample
|
||||||
mBlockFiles.insert(mBlockFiles.begin()+0,unorderedBlocks[i]);
|
firstBlock = ptr;
|
||||||
|
mBlockFiles.insert(mBlockFiles.begin(), unorderedBlocks[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//otherwise no priority
|
//otherwise no priority
|
||||||
|
if ( !firstBlock )
|
||||||
|
firstBlock = ptr;
|
||||||
mBlockFiles.push_back(unorderedBlocks[i]);
|
mBlockFiles.push_back(unorderedBlocks[i]);
|
||||||
}
|
}
|
||||||
if(mMaxBlockFiles< (int) mBlockFiles.size())
|
if(mMaxBlockFiles< (int) mBlockFiles.size())
|
||||||
@ -270,7 +274,8 @@ void ODComputeSummaryTask::OrderBlockFiles
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Otherwise, let it be deleted and forget about it.
|
// The block file disappeared.
|
||||||
|
// Let it be deleted and forget about it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ protected:
|
|||||||
|
|
||||||
///Orders the input as either On-Demand or default layered order.
|
///Orders the input as either On-Demand or default layered order.
|
||||||
void OrderBlockFiles
|
void OrderBlockFiles
|
||||||
(std::vector< std::shared_ptr< ODPCMAliasBlockFile > > &unorderedBlocks);
|
(std::vector< std::weak_ptr< ODPCMAliasBlockFile > > &unorderedBlocks);
|
||||||
|
|
||||||
///tells us whether or not Update has been run at least once.
|
///tells us whether or not Update has been run at least once.
|
||||||
void MarkUpdateRan();
|
void MarkUpdateRan();
|
||||||
@ -73,7 +73,7 @@ protected:
|
|||||||
|
|
||||||
//mBlockFiles is touched on several threads- the OD terminate thread, and the task thread, so we need to mutex it.
|
//mBlockFiles is touched on several threads- the OD terminate thread, and the task thread, so we need to mutex it.
|
||||||
ODLock mBlockFilesMutex;
|
ODLock mBlockFilesMutex;
|
||||||
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > mBlockFiles;
|
std::vector< std::weak_ptr< ODPCMAliasBlockFile > > mBlockFiles;
|
||||||
int mMaxBlockFiles;
|
int mMaxBlockFiles;
|
||||||
ODLock mHasUpdateRanMutex;
|
ODLock mHasUpdateRanMutex;
|
||||||
bool mHasUpdateRan;
|
bool mHasUpdateRan;
|
||||||
|
@ -48,16 +48,13 @@ void ODDecodeTask::DoSomeInternal()
|
|||||||
|
|
||||||
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
|
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
|
||||||
{
|
{
|
||||||
const auto &bf = mBlockFiles[0];
|
const auto bf = mBlockFiles[0].lock();
|
||||||
|
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
//first check to see if the ref count is at least 2. It should have one
|
if(bf)
|
||||||
//from when we added it to this instance's mBlockFiles array, and one from
|
|
||||||
//the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
|
|
||||||
if(bf.use_count()>=2)
|
|
||||||
{
|
{
|
||||||
//OD TODO: somehow pass the bf a reference to the decoder that manages it's file.
|
//OD TODO: somehow pass the bf a reference to the decoder that manages its file.
|
||||||
//we need to ensure that the filename won't change or be moved. We do this by calling LockRead(),
|
//we need to ensure that the filename won't change or be moved. We do this by calling LockRead(),
|
||||||
//which the dirmanager::EnsureSafeFilename also does.
|
//which the dirmanager::EnsureSafeFilename also does.
|
||||||
bf->LockRead();
|
bf->LockRead();
|
||||||
@ -77,6 +74,7 @@ void ODDecodeTask::DoSomeInternal()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// The block file disappeared.
|
||||||
//the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
|
//the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
|
||||||
//because now there is less work to do.
|
//because now there is less work to do.
|
||||||
mMaxBlockFiles--;
|
mMaxBlockFiles--;
|
||||||
@ -123,7 +121,7 @@ bool ODDecodeTask::SeekingAllowed()
|
|||||||
///by default creates the order of the wavetrack to load.
|
///by default creates the order of the wavetrack to load.
|
||||||
void ODDecodeTask::Update()
|
void ODDecodeTask::Update()
|
||||||
{
|
{
|
||||||
std::vector< std::shared_ptr< ODDecodeBlockFile > > tempBlocks;
|
std::vector< std::weak_ptr< ODDecodeBlockFile > > tempBlocks;
|
||||||
|
|
||||||
mWaveTrackMutex.Lock();
|
mWaveTrackMutex.Lock();
|
||||||
|
|
||||||
@ -162,12 +160,16 @@ void ODDecodeTask::Update()
|
|||||||
));
|
));
|
||||||
|
|
||||||
//these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
|
//these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
|
||||||
while(insertCursor<(int)tempBlocks.size()&&
|
{
|
||||||
tempBlocks[insertCursor]->GetStart() + tempBlocks[insertCursor]->GetClipOffset() <
|
std::shared_ptr< ODDecodeBlockFile > ptr;
|
||||||
oddbFile->GetStart() + oddbFile->GetClipOffset())
|
while(insertCursor < (int)tempBlocks.size() &&
|
||||||
insertCursor++;
|
(!(ptr = tempBlocks[insertCursor].lock()) ||
|
||||||
|
ptr->GetStart() + ptr->GetClipOffset() <
|
||||||
|
oddbFile->GetStart() + oddbFile->GetClipOffset()))
|
||||||
|
insertCursor++;
|
||||||
|
}
|
||||||
|
|
||||||
tempBlocks.insert(tempBlocks.begin()+insertCursor++, oddbFile);
|
tempBlocks.insert(tempBlocks.begin() + insertCursor++, oddbFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +187,7 @@ void ODDecodeTask::Update()
|
|||||||
|
|
||||||
///Orders the input as either On-Demand or default layered order.
|
///Orders the input as either On-Demand or default layered order.
|
||||||
void ODDecodeTask::OrderBlockFiles
|
void ODDecodeTask::OrderBlockFiles
|
||||||
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks)
|
(std::vector< std::weak_ptr< ODDecodeBlockFile > > &unorderedBlocks)
|
||||||
{
|
{
|
||||||
mBlockFiles.clear();
|
mBlockFiles.clear();
|
||||||
//TODO:order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
|
//TODO:order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
|
||||||
@ -194,28 +196,30 @@ void ODDecodeTask::OrderBlockFiles
|
|||||||
|
|
||||||
//find the startpoint
|
//find the startpoint
|
||||||
auto processStartSample = GetDemandSample();
|
auto processStartSample = GetDemandSample();
|
||||||
for(int i= ((int)unorderedBlocks.size())-1;i>= 0;i--)
|
std::shared_ptr< ODDecodeBlockFile > firstBlock;
|
||||||
|
for(auto i = unorderedBlocks.size(); i--; )
|
||||||
{
|
{
|
||||||
//check to see if the refcount is at least two before we add it to the list.
|
auto ptr = unorderedBlocks[i].lock();
|
||||||
//There should be one Ref() from the one added by this ODTask, and one from the track.
|
if(ptr)
|
||||||
//If there isn't, then the block was deleted for some reason and we should ignore it.
|
|
||||||
if(unorderedBlocks[i].use_count() >= 2)
|
|
||||||
{
|
{
|
||||||
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
|
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
|
||||||
//and add ones that are closer.
|
//and add ones that are closer.
|
||||||
//since the order is linear right to left, this will add blocks so that the ones on the right side of the target
|
//since the order is linear right to left, this will add blocks so that the ones on the right side of the target
|
||||||
//are processed first, with the ones closer being processed earlier. Then the ones on the left side get processed.
|
//are processed first, with the ones closer being processed earlier. Then the ones on the left side get processed.
|
||||||
if(mBlockFiles.size() &&
|
if(mBlockFiles.size() &&
|
||||||
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
|
ptr->GetGlobalEnd() >= processStartSample &&
|
||||||
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
|
( firstBlock->GetGlobalEnd() < processStartSample ||
|
||||||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart()) )
|
ptr->GetGlobalStart() <= firstBlock->GetGlobalStart()) )
|
||||||
{
|
{
|
||||||
//insert at the front of the list if we get blockfiles that are after the demand sample
|
//insert at the front of the list if we get blockfiles that are after the demand sample
|
||||||
mBlockFiles.insert(mBlockFiles.begin()+0,unorderedBlocks[i]);
|
firstBlock = ptr;
|
||||||
|
mBlockFiles.insert(mBlockFiles.begin(), unorderedBlocks[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//otherwise no priority
|
//otherwise no priority
|
||||||
|
if ( !firstBlock )
|
||||||
|
firstBlock = ptr;
|
||||||
mBlockFiles.push_back(unorderedBlocks[i]);
|
mBlockFiles.push_back(unorderedBlocks[i]);
|
||||||
}
|
}
|
||||||
if(mMaxBlockFiles< (int) mBlockFiles.size())
|
if(mMaxBlockFiles< (int) mBlockFiles.size())
|
||||||
@ -223,6 +227,7 @@ void ODDecodeTask::OrderBlockFiles
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// The block file disappeared.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,10 +86,10 @@ protected:
|
|||||||
|
|
||||||
///Orders the input as either On-Demand or default layered order.
|
///Orders the input as either On-Demand or default layered order.
|
||||||
void OrderBlockFiles
|
void OrderBlockFiles
|
||||||
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks);
|
(std::vector< std::weak_ptr< ODDecodeBlockFile > > &unorderedBlocks);
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<ODDecodeBlockFile>> mBlockFiles;
|
std::vector<std::weak_ptr<ODDecodeBlockFile>> mBlockFiles;
|
||||||
std::vector<movable_ptr<ODFileDecoder>> mDecoders;
|
std::vector<movable_ptr<ODFileDecoder>> mDecoders;
|
||||||
|
|
||||||
int mMaxBlockFiles;
|
int mMaxBlockFiles;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user