1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-03-07 15:05:38 +01:00

Access BlockFile::mFileName without copying, with proper multithreading cautions

This commit is contained in:
Paul Licameli
2016-04-17 11:42:33 -04:00
parent 94cf94718e
commit 3d102a3390
8 changed files with 65 additions and 32 deletions

View File

@@ -941,7 +941,8 @@ bool DirManager::ContainsBlockFile(const BlockFile *b) const
{
if (!b)
return false;
BlockHash::const_iterator it = mBlockFileHash.find(b->GetFileName().GetName());
auto result = b->GetFileName();
BlockHash::const_iterator it = mBlockFileHash.find(result.name.GetName());
return it != mBlockFileHash.end() && it->second == b;
}
@@ -957,7 +958,8 @@ bool DirManager::ContainsBlockFile(const wxString &filepath) const
// the BlockFile.
BlockFile *DirManager::CopyBlockFile(BlockFile *b)
{
const auto &fn = b->GetFileName();
auto result = b->GetFileName();
const auto &fn = result.name;
if (!b->IsLocked()) {
b->Ref();
@@ -996,6 +998,9 @@ BlockFile *DirManager::CopyBlockFile(BlockFile *b)
return NULL;
}
// Done with fn
result.mLocker.reset();
b2 = b->Copy(std::move(newFile));
if (b2 == NULL)
@@ -1090,7 +1095,7 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
// return a reference to the existing object instead.
//
wxString name = target->GetFileName().GetName();
wxString name = target->GetFileName().name.GetName();
BlockFile *retrieved = mBlockFileHash[name];
if (retrieved) {
// Lock it in order to DELETE it safely, i.e. without having
@@ -1114,23 +1119,24 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
bool DirManager::MoveOrCopyToNewProjectDirectory(BlockFile *f, bool copy)
{
const auto oldFileName = f->GetFileName();
auto result = f->GetFileName();
const auto &oldFileNameRef = result.name;
// Check that this BlockFile corresponds to a file on disk
//ANSWER-ME: Is this checking only for SilentBlockFiles, in which case
// (!oldFileName.IsOk()) is a more correct check?
if (oldFileName.GetName().IsEmpty()) {
if (oldFileNameRef.GetName().IsEmpty()) {
return true;
}
wxFileNameWrapper newFileName;
if (!this->AssignFile(newFileName, oldFileName.GetFullName(), false))
if (!this->AssignFile(newFileName, oldFileNameRef.GetFullName(), false))
return false;
if (newFileName != oldFileName) {
if (newFileName != oldFileNameRef) {
//check to see that summary exists before we copy.
bool summaryExisted = f->IsSummaryAvailable();
auto oldPath = oldFileName.GetFullPath();
auto oldPath = oldFileNameRef.GetFullPath();
auto newPath = newFileName.GetFullPath();
if (summaryExisted) {
auto success = copy
@@ -1139,11 +1145,21 @@ bool DirManager::MoveOrCopyToNewProjectDirectory(BlockFile *f, bool copy)
if (!success)
return false;
}
f->SetFileName(std::move(newFileName));
//there is a small chance that the summary has begun to be computed on a different thread with the
//original filename. we need to catch this case by waiting for it to finish and then copy.
if (!summaryExisted && (f->IsSummaryAvailable() || f->IsSummaryBeingComputed())) {
// We will need to remember the old file name, so copy it
wxFileName oldFileName{ oldFileNameRef };
// Now we can free any lock (and should, if as the comment below says, we need
// the other threads to progress)
result.mLocker.reset();
f->SetFileName(std::move(newFileName));
//there is a small chance that the summary has begun to be computed on a different thread with the
//original filename. we need to catch this case by waiting for it to finish and then copy.
//block to make sure OD files don't get written while we are changing file names.
//(It is important that OD files set this lock while computing their summary files.)
while(f->IsSummaryBeingComputed() && !f->IsSummaryAvailable())
@@ -1160,6 +1176,11 @@ bool DirManager::MoveOrCopyToNewProjectDirectory(BlockFile *f, bool copy)
return false;
}
}
else {
// Can free this now, and must, because of nonrecursive mutexes
result.mLocker.reset();
f->SetFileName(std::move(newFileName));
}
}
return true;
@@ -1190,7 +1211,7 @@ int DirManager::GetRefCount(BlockFile * f)
void DirManager::Deref(BlockFile * f)
{
wxString theFileName = f->GetFileName().GetName();
const wxString theFileName = f->GetFileName().name.GetName();
//printf("Deref(%d): %s\n",
// f->mRefCount-1,
@@ -1338,7 +1359,8 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
{
ab->ChangeAliasedFileName(wxFileNameWrapper{ renamedFileName });
ab->UnlockRead();
wxPrintf(_("Changed block %s to new alias name\n"), b->GetFileName().GetFullName().c_str());
wxPrintf(_("Changed block %s to new alias name\n"),
b->GetFileName().name.GetFullName().c_str());
}
else if (!b->IsDataAvailable() && db->GetEncodedAudioFilename() == fName) {