1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-06 14:52:34 +02:00

Manage block files with std::shared_ptr, BlockHash stores weak_ptr

This commit is contained in:
Paul Licameli 2016-08-16 10:52:43 -04:00
parent 84ccdca5c3
commit 8b72bd2f92
14 changed files with 51 additions and 230 deletions

View File

@ -101,7 +101,6 @@ ArrayOf<char> BlockFile::fullSummary;
/// @param samples The number of samples this BlockFile contains. /// @param samples The number of samples this BlockFile contains.
BlockFile::BlockFile(wxFileNameWrapper &&fileName, sampleCount samples): BlockFile::BlockFile(wxFileNameWrapper &&fileName, sampleCount samples):
mLockCount(0), mLockCount(0),
mRefCount(1),
mFileName(std::move(fileName)), mFileName(std::move(fileName)),
mLen(samples), mLen(samples),
mSummaryInfo(samples) mSummaryInfo(samples)
@ -165,28 +164,6 @@ bool BlockFile::IsLocked()
return mLockCount > 0; return mLockCount > 0;
} }
/// Increases the reference count of this block by one. Only
/// DirManager should call this method.
void BlockFile::Ref() const
{
mRefCount++;
BLOCKFILE_DEBUG_OUTPUT("Ref", mRefCount);
}
/// Decreases the reference count of this block by one. If this
/// causes the count to become zero, deletes the associated disk
/// file and deletes this object
bool BlockFile::Deref() const
{
mRefCount--;
BLOCKFILE_DEBUG_OUTPUT("Deref", mRefCount);
if (mRefCount <= 0) {
delete this;
return true;
} else
return false;
}
/// Get a buffer containing a summary block describing this sample /// Get a buffer containing a summary block describing this sample
/// data. This must be called by derived classes when they /// data. This must be called by derived classes when they
/// are constructed, to allow them to construct their summary data, /// are constructed, to allow them to construct their summary data,

View File

@ -44,15 +44,12 @@ class SummaryInfo {
class BlockFile; class BlockFile;
using BlockFilePtr = std::shared_ptr<BlockFile>;
// to do: use shared_ptr instead
using BlockFilePtr = BlockFile *;
// to do: make this a synonym for make_shared
template< typename Result, typename... Args > template< typename Result, typename... Args >
inline Result *make_blockfile (Args && ... args) inline std::shared_ptr< Result > make_blockfile (Args && ... args)
{ {
return new Result( std::forward< Args > ( args )... ); return std::make_shared< Result > ( std::forward< Args > ( args )... );
} }
class PROFILE_DLL_API BlockFile /* not final, abstract */ { class PROFILE_DLL_API BlockFile /* not final, abstract */ {
@ -168,17 +165,6 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
private: private:
friend class DirManager;
friend class AudacityApp;
//needed for Ref/Deref access.
friend class ODComputeSummaryTask;
friend class ODDecodeTask;
friend class ODPCMAliasBlockFile;
virtual void Ref() const;
virtual bool Deref() const;
virtual int RefCount(){return mRefCount;}
protected: protected:
/// Calculate summary data for the given sample data /// Calculate summary data for the given sample data
/// Overrides have differing details of memory management /// Overrides have differing details of memory management
@ -199,7 +185,6 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
private: private:
int mLockCount; int mLockCount;
mutable int mRefCount;
static ArrayOf<char> fullSummary; static ArrayOf<char> fullSummary;

View File

@ -94,10 +94,6 @@ static void ReplaceBlockFiles(AudacityProject *project,
const auto src = &*f; const auto src = &*f;
if (hash.count( src ) > 0) { if (hash.count( src ) > 0) {
const auto &dst = hash[src]; const auto &dst = hash[src];
dirManager->Deref(src);
dirManager->Ref(dst);
f = dst; f = dst;
} }
} }
@ -223,11 +219,6 @@ static void RemoveDependencies(AudacityProject *project,
// However, that didn't actually change any references to these // However, that didn't actually change any references to these
// blockfiles in the Sequences, so we do that next... // blockfiles in the Sequences, so we do that next...
ReplaceBlockFiles(project, blockFileHash); ReplaceBlockFiles(project, blockFileHash);
// Subtract one from reference count of NEW block files; they're
// now all referenced the proper number of times by the Sequences
for (const auto &pair : blockFileHash)
dirManager->Deref(pair.second);
} }
// //

View File

@ -454,7 +454,7 @@ bool DirManager::SetProject(wxString& newProjPath, wxString& newProjName, const
int count = 0; int count = 0;
while ((iter != mBlockFileHash.end()) && success) while ((iter != mBlockFileHash.end()) && success)
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -486,7 +486,7 @@ bool DirManager::SetProject(wxString& newProjPath, wxString& newProjName, const
BlockHash::iterator iter = mBlockFileHash.begin(); BlockHash::iterator iter = mBlockFileHash.begin();
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -726,7 +726,7 @@ auto DirManager::GetBalanceInfo() -> BalanceInfo &
auto it = mBlockFileHash.begin(), end = mBlockFileHash.end(); auto it = mBlockFileHash.begin(), end = mBlockFileHash.end();
while (it != end) while (it != end)
{ {
BlockFilePtr ptr { it->second }; BlockFilePtr ptr { it->second.lock() };
if (!ptr) { if (!ptr) {
auto name = it->first; auto name = it->first;
mBlockFileHash.erase( it++ ); mBlockFileHash.erase( it++ );
@ -1006,7 +1006,7 @@ bool DirManager::ContainsBlockFile(const BlockFile *b) const
BlockHash::const_iterator it = mBlockFileHash.find(result.name.GetName()); BlockHash::const_iterator it = mBlockFileHash.find(result.name.GetName());
if (it == mBlockFileHash.end()) if (it == mBlockFileHash.end())
return false; return false;
BlockFilePtr ptr = it->second; BlockFilePtr ptr = it->second.lock();
return ptr && (b == &*ptr); return ptr && (b == &*ptr);
} }
@ -1015,7 +1015,7 @@ bool DirManager::ContainsBlockFile(const wxString &filepath) const
// check what the hash returns in case the blockfile is from a different project // check what the hash returns in case the blockfile is from a different project
BlockHash::const_iterator it = mBlockFileHash.find(filepath); BlockHash::const_iterator it = mBlockFileHash.find(filepath);
return it != mBlockFileHash.end() && return it != mBlockFileHash.end() &&
BlockFilePtr{ it->second }; BlockFilePtr{ it->second.lock() };
} }
// Adds one to the reference count of the block file, // Adds one to the reference count of the block file,
@ -1027,7 +1027,6 @@ BlockFilePtr DirManager::CopyBlockFile(const BlockFilePtr &b)
const auto &fn = result.name; const auto &fn = result.name;
if (!b->IsLocked()) { if (!b->IsLocked()) {
b->Ref();
//mchinen:July 13 2009 - not sure about this, but it needs to be added to the hash to be able to save if not locked. //mchinen:July 13 2009 - not sure about this, but it needs to be added to the hash to be able to save if not locked.
//note that this shouldn't hurt mBlockFileHash's that already contain the filename, since it should just overwrite. //note that this shouldn't hurt mBlockFileHash's that already contain the filename, since it should just overwrite.
//but it's something to watch out for. //but it's something to watch out for.
@ -1148,7 +1147,6 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
// See http://bugzilla.audacityteam.org/show_bug.cgi?id=451#c13. // See http://bugzilla.audacityteam.org/show_bug.cgi?id=451#c13.
// Lock pBlockFile so that the ~BlockFile() will not DELETE the file on disk. // Lock pBlockFile so that the ~BlockFile() will not DELETE the file on disk.
pBlockFile->Lock(); pBlockFile->Lock();
delete pBlockFile;
return false; return false;
} }
else else
@ -1162,7 +1160,7 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
wxString name = target->GetFileName().name.GetName(); wxString name = target->GetFileName().name.GetName();
auto &wRetrieved = mBlockFileHash[name]; auto &wRetrieved = mBlockFileHash[name];
BlockFilePtr retrieved = wRetrieved; BlockFilePtr retrieved = wRetrieved.lock();
if (retrieved) { if (retrieved) {
// Lock it in order to DELETE it safely, i.e. without having // Lock it in order to DELETE it safely, i.e. without having
// it DELETE the file, too... // it DELETE the file, too...
@ -1260,38 +1258,6 @@ bool DirManager::CopyToNewProjectDirectory(BlockFile *f)
return MoveOrCopyToNewProjectDirectory(f, true); return MoveOrCopyToNewProjectDirectory(f, true);
} }
void DirManager::Ref(BlockFile * f)
{
f->Ref();
//printf("Ref(%d): %s\n",
// f->mRefCount,
// (const char *)f->mFileName.GetFullPath().mb_str());
}
int DirManager::GetRefCount(BlockFile * f)
{
return f->mRefCount;
}
void DirManager::Deref(BlockFile * f)
{
const wxString theFileName = f->GetFileName().name.GetName();
//printf("Deref(%d): %s\n",
// f->mRefCount-1,
// (const char *)f->mFileName.GetFullPath().mb_str());
if (f->Deref()) {
// If Deref() returned true, the reference count reached zero
// and this block is no longer needed. Remove it from the hash
// table.
mBlockFileHash.erase(theFileName);
BalanceInfoDel(theFileName);
}
}
bool DirManager::EnsureSafeFilename(const wxFileName &fName) bool DirManager::EnsureSafeFilename(const wxFileName &fName)
{ {
// Quick check: If it's not even in our alias list, // Quick check: If it's not even in our alias list,
@ -1352,7 +1318,7 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
BlockHash::iterator iter = mBlockFileHash.begin(); BlockHash::iterator iter = mBlockFileHash.begin();
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -1395,7 +1361,7 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
BlockHash::iterator iter = mBlockFileHash.begin(); BlockHash::iterator iter = mBlockFileHash.begin();
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -1423,7 +1389,7 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
BlockHash::iterator iter = mBlockFileHash.begin(); BlockHash::iterator iter = mBlockFileHash.begin();
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -1558,7 +1524,7 @@ _("Project check of \"%s\" folder \
while (iter != missingAliasedFileAUFHash.end()) while (iter != missingAliasedFileAUFHash.end())
{ {
// This type cast is safe. We checked that it's an alias block file earlier. // This type cast is safe. We checked that it's an alias block file earlier.
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
wxASSERT(b); wxASSERT(b);
if (!b) if (!b)
@ -1625,7 +1591,7 @@ _("Project check of \"%s\" folder \
BlockHash::iterator iter = missingAUFHash.begin(); BlockHash::iterator iter = missingAUFHash.begin();
while (iter != missingAUFHash.end()) while (iter != missingAUFHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
wxASSERT(b); wxASSERT(b);
if (!b) if (!b)
@ -1689,7 +1655,7 @@ _("Project check of \"%s\" folder \
BlockHash::iterator iter = missingAUHash.begin(); BlockHash::iterator iter = missingAUHash.begin();
while (iter != missingAUHash.end()) while (iter != missingAUHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
wxASSERT(b); wxASSERT(b);
if (!b) if (!b)
@ -1801,7 +1767,7 @@ void DirManager::FindMissingAliasedFiles(
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
wxString key = iter->first; // file name and extension wxString key = iter->first; // file name and extension
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -1841,7 +1807,7 @@ void DirManager::FindMissingAUFs(
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
const wxString &key = iter->first; const wxString &key = iter->first;
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -1871,7 +1837,7 @@ void DirManager::FindMissingAUs(
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
const wxString &key = iter->first; const wxString &key = iter->first;
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -1975,7 +1941,7 @@ void DirManager::FillBlockfilesCache()
iter = mBlockFileHash.begin(); iter = mBlockFileHash.begin();
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -1995,7 +1961,7 @@ void DirManager::FillBlockfilesCache()
int current = 0; int current = 0;
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -2020,7 +1986,7 @@ void DirManager::WriteCacheToDisk()
iter = mBlockFileHash.begin(); iter = mBlockFileHash.begin();
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;
@ -2040,7 +2006,7 @@ void DirManager::WriteCacheToDisk()
int current = 0; int current = 0;
while (iter != mBlockFileHash.end()) while (iter != mBlockFileHash.end())
{ {
BlockFilePtr b = iter->second; BlockFilePtr b = iter->second.lock();
if (!b) if (!b)
continue; continue;

View File

@ -34,9 +34,10 @@ class SequenceTest;
WX_DECLARE_HASH_MAP(int, int, wxIntegerHash, wxIntegerEqual, DirHash); WX_DECLARE_HASH_MAP(int, int, wxIntegerHash, wxIntegerEqual, DirHash);
class BlockFile; class BlockFile;
using BlockFilePtr = BlockFile *; using BlockFilePtr = std::shared_ptr<BlockFile>;
WX_DECLARE_HASH_MAP(wxString, BlockFilePtr, wxStringHash, wxStringEqual, BlockHash); WX_DECLARE_HASH_MAP(wxString, std::weak_ptr<BlockFile>, wxStringHash,
wxStringEqual, BlockHash);
wxMemorySize GetFreeMemory(); wxMemorySize GetFreeMemory();
@ -101,12 +102,6 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
bool EnsureSafeFilename(const wxFileName &fName); bool EnsureSafeFilename(const wxFileName &fName);
void Ref(BlockFile * f);
void Deref(BlockFile * f);
// For debugging only
int GetRefCount(BlockFile * f);
void SetLoadingTarget(BlockArray *pArray, unsigned idx) void SetLoadingTarget(BlockArray *pArray, unsigned idx)
{ {
mLoadingTarget = pArray; mLoadingTarget = pArray;

View File

@ -34,6 +34,7 @@ using std::isinf;
namespace std { namespace std {
using std::tr1::shared_ptr; using std::tr1::shared_ptr;
using std::tr1::weak_ptr; using std::tr1::weak_ptr;
using std::tr1::static_pointer_cast;
using std::tr1::remove_reference; using std::tr1::remove_reference;
template<typename X> struct default_delete template<typename X> struct default_delete

View File

@ -75,19 +75,6 @@ Sequence::Sequence(const Sequence &orig, const std::shared_ptr<DirManager> &proj
Sequence::~Sequence() Sequence::~Sequence()
{ {
DerefAllFiles();
}
void Sequence::DerefAllFiles()
{
for (size_t i = 0, nn = mBlock.size(); i < nn; i++)
{
BlockFile *& pOldFile = mBlock[i].f;
if (pOldFile) {
mDirManager->Deref(pOldFile);
pOldFile = NULL;
}
}
} }
sampleCount Sequence::GetMaxBlockSize() const sampleCount Sequence::GetMaxBlockSize() const
@ -210,8 +197,6 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged)
// Invalidate all the old, non-aliased block files. // Invalidate all the old, non-aliased block files.
// Aliased files will be converted at save, per comment above. // Aliased files will be converted at save, per comment above.
DerefAllFiles();
// Replace with NEW blocks. // Replace with NEW blocks.
mBlock.swap(newBlockArray); mBlock.swap(newBlockArray);
} }
@ -550,7 +535,6 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
auto file = auto file =
mDirManager->NewSimpleBlockFile(buffer.ptr(), largerBlockLen, mSampleFormat); mDirManager->NewSimpleBlockFile(buffer.ptr(), largerBlockLen, mSampleFormat);
mDirManager->Deref(block.f);
block.f = file; block.f = file;
for (unsigned int i = b + 1; i < numBlocks; i++) for (unsigned int i = b + 1; i < numBlocks; i++)
@ -635,8 +619,6 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
Blockify(newBlock, s + lastStart, sampleBuffer.ptr(), rightLen); Blockify(newBlock, s + lastStart, sampleBuffer.ptr(), rightLen);
} }
mDirManager->Deref(splitBlock.f);
// Copy remaining blocks to NEW block array and // Copy remaining blocks to NEW block array and
// swap the NEW block array in for the old // swap the NEW block array in for the old
for (i = b + 1; i < numBlocks; i++) for (i = b + 1; i < numBlocks; i++)
@ -681,13 +663,10 @@ bool Sequence::InsertSilence(sampleCount s0, sampleCount len)
silentFile = make_blockfile<SilentBlockFile>(idealSamples); silentFile = make_blockfile<SilentBlockFile>(idealSamples);
while (len >= idealSamples) { while (len >= idealSamples) {
sTrack.mBlock.push_back(SeqBlock(silentFile, pos)); sTrack.mBlock.push_back(SeqBlock(silentFile, pos));
mDirManager->Ref(silentFile);
pos += idealSamples; pos += idealSamples;
len -= idealSamples; len -= idealSamples;
} }
if (silentFile)
mDirManager->Deref(silentFile);
if (len) { if (len) {
sTrack.mBlock.push_back(SeqBlock( sTrack.mBlock.push_back(SeqBlock(
make_blockfile<SilentBlockFile>(len), pos)); make_blockfile<SilentBlockFile>(len), pos));
@ -1151,11 +1130,8 @@ bool Sequence::CopyWrite(SampleBuffer &scratch,
Read(scratch.ptr(), mSampleFormat, b, 0, length); Read(scratch.ptr(), mSampleFormat, b, 0, length);
memcpy(scratch.ptr() + start*sampleSize, buffer, len*sampleSize); memcpy(scratch.ptr() + start*sampleSize, buffer, len*sampleSize);
BlockFile *const oldBlockFile = b.f;
b.f = mDirManager->NewSimpleBlockFile(scratch.ptr(), length, mSampleFormat); b.f = mDirManager->NewSimpleBlockFile(scratch.ptr(), length, mSampleFormat);
mDirManager->Deref(oldBlockFile);
return true; return true;
} }
@ -1233,7 +1209,6 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format,
if (start == block.start && if (start == block.start &&
blen == fileLength) { blen == fileLength) {
mDirManager->Deref(block.f);
block.f = make_blockfile<SilentBlockFile>(blen); block.f = make_blockfile<SilentBlockFile>(blen);
} }
else { else {
@ -1545,7 +1520,6 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format,
static_cast< SimpleBlockFile * >( &*newLastBlock.f ) static_cast< SimpleBlockFile * >( &*newLastBlock.f )
->SaveXML( *blockFileLog ); ->SaveXML( *blockFileLog );
mDirManager->Deref(lastBlock.f);
lastBlock = newLastBlock; lastBlock = newLastBlock;
len -= addLen; len -= addLen;
@ -1651,12 +1625,10 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
Read(scratch.ptr() + (pos * sampleSize), mSampleFormat, Read(scratch.ptr() + (pos * sampleSize), mSampleFormat,
b, pos + len, newLen - pos); b, pos + len, newLen - pos);
BlockFile *const oldFile = b.f;
b = SeqBlock( b = SeqBlock(
mDirManager->NewSimpleBlockFile(scratch.ptr(), newLen, mSampleFormat), mDirManager->NewSimpleBlockFile(scratch.ptr(), newLen, mSampleFormat),
b.start b.start
); );
mDirManager->Deref(oldFile);
for (unsigned int j = b0 + 1; j < numBlocks; j++) for (unsigned int j = b0 + 1; j < numBlocks; j++)
mBlock[j].start -= len; mBlock[j].start -= len;
@ -1705,8 +1677,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
newBlock.erase(newBlock.end() - 1); newBlock.erase(newBlock.end() - 1);
Blockify(newBlock, prepreBlock.start, scratch.ptr(), sum); Blockify(newBlock, prepreBlock.start, scratch.ptr(), sum);
mDirManager->Deref(prepreBlock.f);
} }
} }
else { else {
@ -1714,15 +1684,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
// right on the beginning of a block. // right on the beginning of a block.
} }
if (b0 != b1) {
mDirManager->Deref(preBlock.f);
}
// Next, DELETE blocks strictly between b0 and b1
for (i = b0 + 1; i < b1; i++) {
mDirManager->Deref(mBlock[i].f);
}
// Now, symmetrically, grab the samples in block b1 after the // Now, symmetrically, grab the samples in block b1 after the
// deletion point into postBuffer. If this is enough samples // deletion point into postBuffer. If this is enough samples
// for its own block, or if this would be the last block in // for its own block, or if this would be the last block in
@ -1757,15 +1718,12 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
Blockify(newBlock, start, scratch.ptr(), sum); Blockify(newBlock, start, scratch.ptr(), sum);
b1++; b1++;
mDirManager->Deref(postpostBlock.f);
} }
} }
else { else {
// The sample where we begin deletion happens to fall // The sample where we begin deletion happens to fall
// right on the end of a block. // right on the end of a block.
} }
mDirManager->Deref(postBlock.f);
// Copy the remaining blocks over from the old array // Copy the remaining blocks over from the old array
for (i = b1 + 1; i < numBlocks; i++) for (i = b1 + 1; i < numBlocks; i++)
@ -1822,11 +1780,11 @@ void Sequence::DebugPrintf(wxString *dest) const
for (i = 0; i < mBlock.size(); i++) { for (i = 0; i < mBlock.size(); i++) {
const SeqBlock &seqBlock = mBlock[i]; const SeqBlock &seqBlock = mBlock[i];
*dest += wxString::Format *dest += wxString::Format
(wxT(" Block %3u: start %8lld, len %8lld, refs %d, "), (wxT(" Block %3u: start %8lld, len %8lld, refs %ld, "),
i, i,
(long long) seqBlock.start, (long long) seqBlock.start,
seqBlock.f ? (long long) seqBlock.f->GetLength() : 0, seqBlock.f ? (long long) seqBlock.f->GetLength() : 0,
seqBlock.f ? mDirManager->GetRefCount(seqBlock.f) : 0); seqBlock.f ? seqBlock.f.use_count() : 0);
if (seqBlock.f) if (seqBlock.f)
*dest += seqBlock.f->GetFileName().name.GetFullName(); *dest += seqBlock.f->GetFileName().name.GetFullName();

View File

@ -30,7 +30,7 @@ typedef wxLongLong_t sampleCount; /** < A native 64-bit integer type, because
#endif #endif
class BlockFile; class BlockFile;
using BlockFilePtr = BlockFile *; using BlockFilePtr = std::shared_ptr<BlockFile>;
class DirManager; class DirManager;
@ -238,8 +238,6 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
// Private methods // Private methods
// //
void DerefAllFiles();
int FindBlock(sampleCount pos) const; int FindBlock(sampleCount pos) const;
bool AppendBlock(const SeqBlock &b); bool AppendBlock(const SeqBlock &b);

View File

@ -74,33 +74,6 @@ ODPCMAliasBlockFile::~ODPCMAliasBlockFile()
{ {
} }
/// Increases the reference count of this block by one. Only
/// DirManager should call this method.
/// This method has been overidden to be threadsafe. It is important especially
/// if two blockfiles deref at the same time resulting in a double deletion of the file
void ODPCMAliasBlockFile::Ref() const
{
mRefMutex.Lock();
BlockFile::Ref();
mRefMutex.Unlock();
}
/// Decreases the reference count of this block by one. If this
/// causes the count to become zero, deletes the associated disk
/// file and deletes this object
bool ODPCMAliasBlockFile::Deref() const
{
bool ret;
mDerefMutex.Lock();
ret = BlockFile::Deref();
if(!ret)
{
//Deref returns true when deleted, in which case we should not be touching instance variables, or ever calling this function again.
mDerefMutex.Unlock();
}
return ret;
}
//Check to see if we have the file for these calls. //Check to see if we have the file for these calls.

View File

@ -143,13 +143,6 @@ protected:
sampleFormat format, ArrayOf<char> &cleanup) override; sampleFormat format, ArrayOf<char> &cleanup) override;
private: private:
//Thread-safe versions
void Ref() const override;
bool Deref() const override;
//needed for Ref/Deref access.
friend class DirManager;
friend class ODComputeSummaryTask;
friend class ODDecodeTask;
ODLock mWriteSummaryMutex; ODLock mWriteSummaryMutex;
@ -162,11 +155,6 @@ protected:
//lock the read data - libsndfile can't handle two reads at once? //lock the read data - libsndfile can't handle two reads at once?
mutable ODLock mReadDataMutex; mutable ODLock mReadDataMutex;
//lock the Ref counting
mutable ODLock mDerefMutex;
mutable ODLock mRefMutex;
mutable ODLock mSummaryAvailableMutex; mutable ODLock mSummaryAvailableMutex;
bool mSummaryAvailable; bool mSummaryAvailable;
bool mSummaryBeingComputed; bool mSummaryBeingComputed;

View File

@ -49,8 +49,6 @@ void ODComputeSummaryTask::Terminate()
//The terminate block won't allow DoSomeInternal and this method to be run async, so this is thread-safe. //The terminate block won't allow DoSomeInternal and this method to be run async, so this is thread-safe.
//Deref the block files since they are ref'ed when put into the array. //Deref the block files since they are ref'ed when put into the array.
mBlockFilesMutex.Lock(); mBlockFilesMutex.Lock();
for(unsigned int i=0;i<mBlockFiles.size();i++)
mBlockFiles[i]->Deref();
mBlockFiles.clear(); mBlockFiles.clear();
mBlockFilesMutex.Unlock(); mBlockFilesMutex.Unlock();
} }
@ -78,7 +76,7 @@ void ODComputeSummaryTask::DoSomeInternal()
//first check to see if the ref count is at least 2. It should have one //first check to see if the ref count is at least 2. It should have one
//from when we added it to this instance's mBlockFiles array, and one from //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. //the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
if(bf->RefCount()>=2) if(bf.use_count() >= 2)
{ {
bf->DoWriteSummary(); bf->DoWriteSummary();
success = true; success = true;
@ -93,8 +91,6 @@ void ODComputeSummaryTask::DoSomeInternal()
mMaxBlockFiles--; mMaxBlockFiles--;
} }
//Release the refcount we placed on it.
bf->Deref();
//take it out of the array - we are done with it. //take it out of the array - we are done with it.
mBlockFiles.erase(mBlockFiles.begin()); mBlockFiles.erase(mBlockFiles.begin());
@ -169,7 +165,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<ODPCMAliasBlockFile*> tempBlocks; std::vector< std::shared_ptr< ODPCMAliasBlockFile > > tempBlocks;
mWaveTrackMutex.Lock(); mWaveTrackMutex.Lock();
@ -204,8 +200,8 @@ void ODComputeSummaryTask::Update()
const auto &file = block.f; const auto &file = block.f;
if(file->IsDataAvailable() && !file->IsSummaryAvailable()) if(file->IsDataAvailable() && !file->IsSummaryAvailable())
{ {
file->Ref(); const auto odpcmaFile =
ODPCMAliasBlockFile *const odpcmaFile = static_cast<ODPCMAliasBlockFile*>(file); std::static_pointer_cast<ODPCMAliasBlockFile>(file);
odpcmaFile->SetStart(block.start); odpcmaFile->SetStart(block.start);
odpcmaFile->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate())); odpcmaFile->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate()));
@ -234,11 +230,9 @@ void ODComputeSummaryTask::Update()
///Computes the summary calculation queue order of the blockfiles ///Computes the summary calculation queue order of the blockfiles
void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &unorderedBlocks) void ODComputeSummaryTask::OrderBlockFiles
(std::vector< std::shared_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
{ {
//we are going to take things out of the array. But first deref them since we ref them when we put them in.
for(unsigned int i=0;i<mBlockFiles.size();i++)
mBlockFiles[i]->Deref();
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)
//for now just put them in linear. We start the order from the first block that includes the ondemand sample //for now just put them in linear. We start the order from the first block that includes the ondemand sample
@ -252,7 +246,7 @@ void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &un
//check to see if the refcount is at least two before we add it to the list. //check to see if the refcount is at least two before we add it to the list.
//There should be one Ref() from the one added by this ODTask, and one from the track. //There should be one Ref() from the one added by this ODTask, and one from the track.
//If there isn't, then the block was deleted for some reason and we should ignore it. //If there isn't, then the block was deleted for some reason and we should ignore it.
if(unorderedBlocks[i]->RefCount()>=2) 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.
@ -276,7 +270,6 @@ void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &un
else else
{ {
//Otherwise, let it be deleted and forget about it. //Otherwise, let it be deleted and forget about it.
unorderedBlocks[i]->Deref();
} }
} }
} }

View File

@ -64,7 +64,8 @@ protected:
void Update() override; void Update() override;
///Orders the input as either On-Demand or default layered order. ///Orders the input as either On-Demand or default layered order.
void OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &unorderedBlocks); void OrderBlockFiles
(std::vector< std::shared_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();
@ -72,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<ODPCMAliasBlockFile*> mBlockFiles; std::vector< std::shared_ptr< ODPCMAliasBlockFile > > mBlockFiles;
int mMaxBlockFiles; int mMaxBlockFiles;
int mComputedBlockFiles; int mComputedBlockFiles;
ODLock mHasUpdateRanMutex; ODLock mHasUpdateRanMutex;

View File

@ -56,7 +56,7 @@ void ODDecodeTask::DoSomeInternal()
//first check to see if the ref count is at least 2. It should have one //first check to see if the ref count is at least 2. It should have one
//from when we added it to this instance's mBlockFiles array, and one from //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. //the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
if(bf->RefCount()>=2) 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 it's 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(),
@ -86,7 +86,6 @@ void ODDecodeTask::DoSomeInternal()
//Release the refcount we placed on it if we are successful //Release the refcount we placed on it if we are successful
if(ret >= 0 ) { if(ret >= 0 ) {
bf->Deref();
//take it out of the array - we are done with it. //take it out of the array - we are done with it.
mBlockFiles.erase(mBlockFiles.begin()); mBlockFiles.erase(mBlockFiles.begin());
@ -126,8 +125,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<ODDecodeBlockFile*> tempBlocks;
mWaveTrackMutex.Lock(); mWaveTrackMutex.Lock();
@ -154,12 +152,12 @@ void ODDecodeTask::Update()
{ {
//since we have more than one ODBlockFile, we will need type flags to cast. //since we have more than one ODBlockFile, we will need type flags to cast.
SeqBlock &block = (*blocks)[i]; SeqBlock &block = (*blocks)[i];
BlockFile *const file = block.f; const auto &file = block.f;
ODDecodeBlockFile *oddbFile; std::shared_ptr<ODDecodeBlockFile> oddbFile;
if (!file->IsDataAvailable() && if (!file->IsDataAvailable() &&
(oddbFile = static_cast<ODDecodeBlockFile*>(file))->GetDecodeType() == this->GetODType()) (oddbFile =
std::static_pointer_cast<ODDecodeBlockFile>(file))->GetDecodeType() == this->GetODType())
{ {
file->Ref();
oddbFile->SetStart(block.start); oddbFile->SetStart(block.start);
oddbFile->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate())); oddbFile->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate()));
@ -186,11 +184,9 @@ 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(std::vector<ODDecodeBlockFile*> &unorderedBlocks) void ODDecodeTask::OrderBlockFiles
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks)
{ {
//we are going to take things out of the array. But first deref them since we ref them when we put them in.
for(unsigned int i=0;i<mBlockFiles.size();i++)
mBlockFiles[i]->Deref();
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)
//for now just put them in linear. We start the order from the first block that includes the ondemand sample //for now just put them in linear. We start the order from the first block that includes the ondemand sample
@ -203,7 +199,7 @@ void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlo
//check to see if the refcount is at least two before we add it to the list. //check to see if the refcount is at least two before we add it to the list.
//There should be one Ref() from the one added by this ODTask, and one from the track. //There should be one Ref() from the one added by this ODTask, and one from the track.
//If there isn't, then the block was deleted for some reason and we should ignore it. //If there isn't, then the block was deleted for some reason and we should ignore it.
if(unorderedBlocks[i]->RefCount()>=2) 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.
@ -227,8 +223,6 @@ void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlo
} }
else else
{ {
//Otherwise, let it be deleted and forget about it.
unorderedBlocks[i]->Deref();
} }
} }

View File

@ -85,10 +85,11 @@ protected:
void Update() override; void Update() override;
///Orders the input as either On-Demand or default layered order. ///Orders the input as either On-Demand or default layered order.
void OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlocks); void OrderBlockFiles
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks);
std::vector<ODDecodeBlockFile*> mBlockFiles; std::vector<std::shared_ptr<ODDecodeBlockFile>> mBlockFiles;
std::vector<movable_ptr<ODFileDecoder>> mDecoders; std::vector<movable_ptr<ODFileDecoder>> mDecoders;
int mMaxBlockFiles; int mMaxBlockFiles;