mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-15 23:59:37 +02:00
checking in cleanup of on-demand files following james' review. also speeds up od cursor updating when user clicks for on-demand
This commit is contained in:
parent
016c6ce796
commit
5ccce1ed4b
@ -99,6 +99,12 @@ class ODDecodeBlockFile : public SimpleBlockFile
|
||||
///Gets the value that indicates where the first sample in this block corresponds to the global sequence/clip. Only for display use.
|
||||
sampleCount GetStart(){return mStart;}
|
||||
|
||||
//returns the number of samples from the beginning of the track that this blockfile starts at
|
||||
sampleCount GetGlobalStart(){return mClipOffset+mStart;}
|
||||
|
||||
//returns the number of samples from the beginning of the track that this blockfile ends at
|
||||
sampleCount GetGlobalEnd(){return mClipOffset+mStart+GetLength();}
|
||||
|
||||
//Below calls are overrided just so we can take wxlog calls out, which are not threadsafe.
|
||||
|
||||
/// Reads the specified data from the aliased file using libsndfile
|
||||
|
@ -110,6 +110,13 @@ class ODPCMAliasBlockFile : public PCMAliasBlockFile
|
||||
///Gets the number of samples the clip associated with this blockfile is offset by.
|
||||
sampleCount GetClipOffset(){return mClipOffset;}
|
||||
|
||||
//returns the number of samples from the beginning of the track that this blockfile starts at
|
||||
sampleCount GetGlobalStart(){return mClipOffset+mStart;}
|
||||
|
||||
//returns the number of samples from the beginning of the track that this blockfile ends at
|
||||
sampleCount GetGlobalEnd(){return mClipOffset+mStart+GetLength();}
|
||||
|
||||
|
||||
//Below calls are overrided just so we can take wxlog calls out, which are not threadsafe.
|
||||
|
||||
/// Reads the specified data from the aliased file using libsndfile
|
||||
|
@ -102,7 +102,10 @@ void ODComputeSummaryTask::DoSomeInternal()
|
||||
//take it out of the array - we are done with it.
|
||||
mBlockFiles.erase(mBlockFiles.begin());
|
||||
|
||||
//This is a bit of a convenience in case someone tries to terminate the task by closing the trackpanel or window.
|
||||
//ODComputeSummaryTask::Terminate() uses this lock to remove everything, and we don't want it to wait since the UI is being blocked.
|
||||
mBlockFilesMutex.Unlock();
|
||||
wxThread::This()->Yield();
|
||||
mBlockFilesMutex.Lock();
|
||||
|
||||
|
||||
@ -187,21 +190,22 @@ void ODComputeSummaryTask::Update()
|
||||
|
||||
//gather all the blockfiles that we should process in the wavetrack.
|
||||
WaveClipList::compatibility_iterator node = mWaveTracks[j]->GetClipIterator();
|
||||
|
||||
int numBlocksDone;
|
||||
|
||||
while(node) {
|
||||
clip = node->GetData();
|
||||
seq = clip->GetSequence();
|
||||
//TODO:this lock is way to big since the whole file is one sequence. find a way to break it down.
|
||||
//This lock may be way too big since the whole file is one sequence.
|
||||
//TODO: test for large files and find a way to break it down.
|
||||
seq->LockDeleteUpdateMutex();
|
||||
|
||||
//See Sequence::Delete() for why need this for now..
|
||||
//We don't need the mBlockFilesMutex here because it is only for the vector list.
|
||||
//These are existing blocks, and its wavetrack or blockfiles won't be deleted because
|
||||
//of the respective mWaveTrackMutex lock and LockDeleteUpdateMutex() call.
|
||||
blocks = clip->GetSequenceBlockArray();
|
||||
int i;
|
||||
int numBlocksIn;
|
||||
int insertCursor;
|
||||
|
||||
numBlocksIn=0;
|
||||
insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n)
|
||||
|
||||
for(i=0; i<(int)blocks->GetCount(); i++)
|
||||
@ -219,21 +223,9 @@ void ODComputeSummaryTask::Update()
|
||||
(sampleCount)(((ODPCMAliasBlockFile*)blocks->Item(i)->f)->GetStart()+((ODPCMAliasBlockFile*)blocks->Item(i)->f)->GetClipOffset()))
|
||||
insertCursor++;
|
||||
|
||||
|
||||
tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODPCMAliasBlockFile*)blocks->Item(i)->f);
|
||||
|
||||
//this next bit ensures that we are spacing the blockfiles over multiple wavetracks evenly.
|
||||
//if((j+1)*numBlocksIn>tempBlocks.size())
|
||||
// tempBlocks.push_back((ODPCMAliasBlockFile*)blocks->Item(i)->f);
|
||||
// else
|
||||
// tempBlocks.insert(tempBlocks.begin()+(j+1)*numBlocksIn, (ODPCMAliasBlockFile*)blocks->Item(i)->f);
|
||||
//
|
||||
|
||||
numBlocksIn++;
|
||||
}
|
||||
}
|
||||
numBlocksDone = numBlocksIn;
|
||||
|
||||
seq->UnlockDeleteUpdateMutex();
|
||||
node = node->GetNext();
|
||||
}
|
||||
@ -260,7 +252,8 @@ void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &un
|
||||
mBlockFiles.clear();
|
||||
//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
|
||||
//(which the user sets by clicking.) note that this code is pretty hacky - it assumes that the array is sorted in time.
|
||||
//(which the user sets by clicking.)
|
||||
//Note that this code assumes that the array is sorted in time.
|
||||
|
||||
//find the startpoint
|
||||
sampleCount processStartSample = GetDemandSample();
|
||||
@ -271,9 +264,12 @@ void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &un
|
||||
//If there isn't, then the block was deleted for some reason and we should ignore it.
|
||||
if(unorderedBlocks[i]->RefCount()>=2)
|
||||
{
|
||||
if(mBlockFiles.size() && (unorderedBlocks[i]->GetStart()+unorderedBlocks[i]->GetClipOffset()) + unorderedBlocks[i]->GetLength() >=processStartSample &&
|
||||
( (mBlockFiles[0]->GetStart()+mBlockFiles[0]->GetClipOffset()) + mBlockFiles[0]->GetLength() < processStartSample ||
|
||||
(unorderedBlocks[i]->GetStart()+unorderedBlocks[i]->GetClipOffset()) <= (mBlockFiles[0]->GetStart() +mBlockFiles[0]->GetClipOffset()))
|
||||
//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.
|
||||
if(mBlockFiles.size() &&
|
||||
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
|
||||
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
|
||||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart())
|
||||
)
|
||||
{
|
||||
//insert at the front of the list if we get blockfiles that are after the demand sample
|
||||
@ -294,10 +290,4 @@ void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &un
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ODComputeSummaryTask::ODUpdate()
|
||||
{
|
||||
//clear old blockFiles and do something smarter.
|
||||
|
||||
}
|
||||
}
|
@ -68,9 +68,6 @@ protected:
|
||||
///Then it updates in the OD manner.
|
||||
virtual void Update();
|
||||
|
||||
///Readjusts the blockfile order to start at the new cursor.
|
||||
virtual void ODUpdate();
|
||||
|
||||
///Orders the input as either On-Demand or default layered order.
|
||||
void OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &unorderedBlocks);
|
||||
|
||||
|
@ -124,8 +124,7 @@ void ODDecodeTask::Update()
|
||||
|
||||
//gather all the blockfiles that we should process in the wavetrack.
|
||||
WaveClipList::compatibility_iterator node = mWaveTracks[j]->GetClipIterator();
|
||||
|
||||
int numBlocksDone;
|
||||
|
||||
while(node) {
|
||||
clip = node->GetData();
|
||||
seq = clip->GetSequence();
|
||||
@ -135,11 +134,8 @@ void ODDecodeTask::Update()
|
||||
//See Sequence::Delete() for why need this for now..
|
||||
blocks = clip->GetSequenceBlockArray();
|
||||
int i;
|
||||
int numBlocksIn;
|
||||
int insertCursor;
|
||||
|
||||
numBlocksIn=0;
|
||||
|
||||
insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n)
|
||||
for(i=0; i<(int)blocks->GetCount(); i++)
|
||||
{
|
||||
@ -156,12 +152,9 @@ void ODDecodeTask::Update()
|
||||
(sampleCount)(((ODDecodeBlockFile*)blocks->Item(i)->f)->GetStart()+((ODDecodeBlockFile*)blocks->Item(i)->f)->GetClipOffset()))
|
||||
insertCursor++;
|
||||
|
||||
|
||||
tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODDecodeBlockFile*)blocks->Item(i)->f);
|
||||
numBlocksIn++;
|
||||
}
|
||||
}
|
||||
numBlocksDone = numBlocksIn;
|
||||
|
||||
seq->UnlockDeleteUpdateMutex();
|
||||
node = node->GetNext();
|
||||
@ -196,10 +189,14 @@ void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlo
|
||||
//If there isn't, then the block was deleted for some reason and we should ignore it.
|
||||
if(unorderedBlocks[i]->RefCount()>=2)
|
||||
{
|
||||
if(mBlockFiles.size() && (unorderedBlocks[i]->GetStart()+unorderedBlocks[i]->GetClipOffset()) + unorderedBlocks[i]->GetLength() >=processStartSample &&
|
||||
( (mBlockFiles[0]->GetStart()+mBlockFiles[0]->GetClipOffset()) + mBlockFiles[0]->GetLength() < processStartSample ||
|
||||
(unorderedBlocks[i]->GetStart()+unorderedBlocks[i]->GetClipOffset()) <= (mBlockFiles[0]->GetStart() +mBlockFiles[0]->GetClipOffset()))
|
||||
)
|
||||
//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.
|
||||
//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.
|
||||
if(mBlockFiles.size() &&
|
||||
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
|
||||
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
|
||||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart()) )
|
||||
{
|
||||
//insert at the front of the list if we get blockfiles that are after the demand sample
|
||||
mBlockFiles.insert(mBlockFiles.begin()+0,unorderedBlocks[i]);
|
||||
@ -221,13 +218,6 @@ void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlo
|
||||
|
||||
}
|
||||
|
||||
void ODDecodeTask::ODUpdate()
|
||||
{
|
||||
//clear old blockFiles and do something smarter.
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
///there could be the ODBlockFiles of several FLACs in one track (after copy and pasting)
|
||||
///so we keep a list of decoders that keep track of the file names, etc, and check the blocks against them.
|
||||
|
@ -80,9 +80,6 @@ protected:
|
||||
///Then it updates in the OD manner.
|
||||
virtual void Update();
|
||||
|
||||
///Readjusts the blockfile order to start at the new cursor.
|
||||
virtual void ODUpdate();
|
||||
|
||||
///Orders the input as either On-Demand or default layered order.
|
||||
void OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlocks);
|
||||
|
||||
|
@ -1,11 +1,18 @@
|
||||
/*
|
||||
* ODManager.cpp
|
||||
* Audacity
|
||||
*
|
||||
* Created by apple on 6/8/08.
|
||||
* Copyright 2008 __MyCompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
/**********************************************************************
|
||||
|
||||
Audacity - A Digital Audio Editor
|
||||
Copyright 1999-2010 Audacity Team
|
||||
File License: wxWidgets
|
||||
|
||||
Michael Chinen
|
||||
|
||||
******************************************************************//**
|
||||
|
||||
\file ODManager.cpp
|
||||
\brief Singleton ODManager class. Is the bridge between client side
|
||||
ODTask requests and internals.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
#include "ODManager.h"
|
||||
#include "ODTask.h"
|
||||
@ -24,82 +31,17 @@ bool gPause=false; //to be loaded in and used with Pause/Resume before ODMan ini
|
||||
/// a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
bool sHasLoadedOD=false;
|
||||
|
||||
|
||||
ODManager* ODManager::pMan=NULL;
|
||||
//init the accessor function pointer - use the first time version of the interface fetcher
|
||||
//first we need to typedef the function pointer type because the compiler doesn't support it in the raw
|
||||
typedef ODManager* (*pfodman)();
|
||||
pfodman ODManager::Instance = &(ODManager::InstanceFirstTime);
|
||||
|
||||
//libsndfile is not threadsafe - this deals with it
|
||||
ODLock sLibSndFileMutex;
|
||||
|
||||
DEFINE_EVENT_TYPE(EVT_ODTASK_UPDATE)
|
||||
|
||||
//OD files are "greater than" non OD files, to produce a sort that has
|
||||
//OD Files at the end
|
||||
int CompareODFileName(const wxString& first, const wxString& second)
|
||||
{
|
||||
bool firstIsOD = false;
|
||||
bool secondIsOD = false;
|
||||
|
||||
if(first.EndsWith(wxT("wav"))||first.EndsWith(wxT("WAV"))||
|
||||
first.EndsWith(wxT("wave"))||first.EndsWith(wxT("WAVE"))||
|
||||
first.EndsWith(wxT("Wav"))||first.EndsWith(wxT("Wave"))||
|
||||
first.EndsWith(wxT("aif"))||first.EndsWith(wxT("AIF"))||
|
||||
first.EndsWith(wxT("aiff"))||first.EndsWith(wxT("AIFF"))||
|
||||
first.EndsWith(wxT("aiff"))||first.EndsWith(wxT("Aif")) )
|
||||
{
|
||||
firstIsOD=true;
|
||||
}
|
||||
if(second.EndsWith(wxT("wav"))||second.EndsWith(wxT("WAV"))||
|
||||
second.EndsWith(wxT("wave"))||second.EndsWith(wxT("WAVE"))||
|
||||
second.EndsWith(wxT("Wav"))||second.EndsWith(wxT("Wave"))||
|
||||
second.EndsWith(wxT("aif"))||second.EndsWith(wxT("AIF"))||
|
||||
second.EndsWith(wxT("aiff"))||second.EndsWith(wxT("AIFF"))||
|
||||
second.EndsWith(wxT("aiff"))||second.EndsWith(wxT("Aif")) )
|
||||
{
|
||||
secondIsOD=true;
|
||||
}
|
||||
|
||||
if(firstIsOD && !secondIsOD)
|
||||
return 1;
|
||||
else if(secondIsOD&&!firstIsOD)
|
||||
return -1;
|
||||
|
||||
return first.Cmp(second);
|
||||
}
|
||||
|
||||
//same as above but OD is less than non-OD
|
||||
int CompareODFirstFileName(const wxString& first, const wxString& second)
|
||||
{
|
||||
bool firstIsOD = false;
|
||||
bool secondIsOD = false;
|
||||
|
||||
if(first.EndsWith(wxT("wav"))||first.EndsWith(wxT("WAV"))||
|
||||
first.EndsWith(wxT("wave"))||first.EndsWith(wxT("WAVE"))||
|
||||
first.EndsWith(wxT("Wav"))||first.EndsWith(wxT("Wave"))||
|
||||
first.EndsWith(wxT("aif"))||first.EndsWith(wxT("AIF"))||
|
||||
first.EndsWith(wxT("aiff"))||first.EndsWith(wxT("AIFF"))||
|
||||
first.EndsWith(wxT("aiff"))||first.EndsWith(wxT("Aif")) )
|
||||
{
|
||||
firstIsOD=true;
|
||||
}
|
||||
if(second.EndsWith(wxT("wav"))||second.EndsWith(wxT("WAV"))||
|
||||
second.EndsWith(wxT("wave"))||second.EndsWith(wxT("WAVE"))||
|
||||
second.EndsWith(wxT("Wav"))||second.EndsWith(wxT("Wave"))||
|
||||
second.EndsWith(wxT("aif"))||second.EndsWith(wxT("AIF"))||
|
||||
second.EndsWith(wxT("aiff"))||second.EndsWith(wxT("AIFF"))||
|
||||
second.EndsWith(wxT("aiff"))||second.EndsWith(wxT("Aif")) )
|
||||
{
|
||||
secondIsOD=true;
|
||||
}
|
||||
|
||||
if(firstIsOD && !secondIsOD)
|
||||
return -1;
|
||||
else if(secondIsOD&&!firstIsOD)
|
||||
return 1;
|
||||
|
||||
//if they are both OD-files, or both non-OD-files, use a normal string comparison
|
||||
//to get alphabetical sorting
|
||||
return first.Cmp(second);
|
||||
}
|
||||
|
||||
//using this with wxStringArray::Sort will give you a list that
|
||||
//is alphabetical, without depending on case. If you use the
|
||||
//default sort, you will get strings with 'R' before 'a', because it is in caps.
|
||||
@ -130,7 +72,7 @@ ODManager::ODManager()
|
||||
mQueueNotEmptyCond = new ODCondition(&mQueueNotEmptyCondLock);
|
||||
}
|
||||
|
||||
//private constructor - delete with static method Quit()
|
||||
//private destructor - delete with static method Quit()
|
||||
ODManager::~ODManager()
|
||||
{
|
||||
//get rid of all the queues. The queues get rid of the tasks, so we don't worry abut them.
|
||||
@ -182,6 +124,7 @@ void ODManager::SignalTaskQueueLoop()
|
||||
void ODManager::RemoveTaskIfInQueue(ODTask* task)
|
||||
{
|
||||
mTasksMutex.Lock();
|
||||
//linear search okay for now, (probably only 1-5 tasks exist at a time.)
|
||||
for(unsigned int i=0;i<mTasks.size();i++)
|
||||
{
|
||||
if(mTasks[i]==task)
|
||||
@ -206,8 +149,7 @@ void ODManager::AddNewTask(ODTask* task, bool lockMutex)
|
||||
mQueuesMutex.Lock();
|
||||
for(unsigned int i=0;i<mQueues.size();i++)
|
||||
{
|
||||
//search for a task containing the lead track.
|
||||
//This may be buggy when adding tracks. We may have to do an exhaustive search instead.
|
||||
//search for a task containing the lead track. wavetrack removal is threadsafe and bound to the mQueuesMutex
|
||||
//note that GetWaveTrack is not threadsafe, but we are assuming task is not running on a different thread yet.
|
||||
if(mQueues[i]->ContainsWaveTrack(task->GetWaveTrack(0)))
|
||||
queue=mQueues[i];
|
||||
@ -234,24 +176,29 @@ void ODManager::AddNewTask(ODTask* task, bool lockMutex)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ODManager* ODManager::Instance()
|
||||
{
|
||||
static ODManager* man=NULL;
|
||||
//this isn't 100% threadsafe but I think Okay for this purpose.
|
||||
|
||||
// wxLogDebug(wxT("Fetching Instance\n"));
|
||||
|
||||
//that switches out the mutex/null check.
|
||||
ODManager* ODManager::InstanceFirstTime()
|
||||
{
|
||||
gODInitedMutex.Lock();
|
||||
if(!man)
|
||||
if(!pMan)
|
||||
{
|
||||
man = new ODManager();
|
||||
man->Init();
|
||||
pMan = new ODManager();
|
||||
pMan->Init();
|
||||
gManagerCreated = true;
|
||||
}
|
||||
gODInitedMutex.Unlock();
|
||||
|
||||
return man;
|
||||
//change the accessor function to use the quicker method.
|
||||
Instance = &(ODManager::InstanceNormal);
|
||||
|
||||
return pMan;
|
||||
}
|
||||
|
||||
//faster method of instance fetching once init is done
|
||||
ODManager* ODManager::InstanceNormal()
|
||||
{
|
||||
return pMan;
|
||||
}
|
||||
|
||||
bool ODManager::IsInstanceCreated()
|
||||
@ -278,7 +225,7 @@ void ODManager::Init()
|
||||
startThread->Run();
|
||||
|
||||
// printf("started thread from init\n");
|
||||
//destruction is taken care of by wx thread code. TODO:Check if pthreads code does this.
|
||||
//destruction of thread is taken care of by thread library
|
||||
}
|
||||
|
||||
void ODManager::DecrementCurrentThreads()
|
||||
@ -328,13 +275,7 @@ void ODManager::Start()
|
||||
mCurrentThreads++;
|
||||
mCurrentThreadsMutex.Unlock();
|
||||
//remove the head
|
||||
mTasksMutex.Lock();
|
||||
//task = mTasks[0];
|
||||
|
||||
//the thread will add it back to the array if the job is not yet done at the end of the thread's run.
|
||||
//mTasks.erase(mTasks.begin());
|
||||
mTasksMutex.Unlock();
|
||||
|
||||
|
||||
//detach a new thread.
|
||||
thread = new ODTaskThread(mTasks[0]);//task);
|
||||
|
||||
@ -392,18 +333,21 @@ void ODManager::Start()
|
||||
|
||||
}
|
||||
|
||||
//static function that prevents ODTasks from being scheduled
|
||||
//does not stop currently running tasks from completing their immediate subtask,
|
||||
//but presumably they will finish within a second
|
||||
void ODManager::Pause(bool pause)
|
||||
{
|
||||
if(IsInstanceCreated())
|
||||
{
|
||||
ODManager::Instance()->mPauseLock.Lock();
|
||||
ODManager::Instance()->mPause = pause;
|
||||
ODManager::Instance()->mPauseLock.Unlock();
|
||||
pMan->mPauseLock.Lock();
|
||||
pMan->mPause = pause;
|
||||
pMan->mPauseLock.Unlock();
|
||||
|
||||
//we should check the queue again.
|
||||
ODManager::Instance()->mQueueNotEmptyCondLock.Lock();
|
||||
ODManager::Instance()->mQueueNotEmptyCond->Signal();
|
||||
ODManager::Instance()->mQueueNotEmptyCondLock.Unlock();
|
||||
pMan->mQueueNotEmptyCondLock.Lock();
|
||||
pMan->mQueueNotEmptyCond->Signal();
|
||||
pMan->mQueueNotEmptyCondLock.Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -420,27 +364,29 @@ void ODManager::Quit()
|
||||
{
|
||||
if(IsInstanceCreated())
|
||||
{
|
||||
ODManager::Instance()->mTerminateMutex.Lock();
|
||||
ODManager::Instance()->mTerminate = true;
|
||||
ODManager::Instance()->mTerminateMutex.Unlock();
|
||||
pMan->mTerminateMutex.Lock();
|
||||
pMan->mTerminate = true;
|
||||
pMan->mTerminateMutex.Unlock();
|
||||
|
||||
ODManager::Instance()->mTerminatedMutex.Lock();
|
||||
while(!ODManager::Instance()->mTerminated)
|
||||
pMan->mTerminatedMutex.Lock();
|
||||
while(!pMan->mTerminated)
|
||||
{
|
||||
ODManager::Instance()->mTerminatedMutex.Unlock();
|
||||
pMan->mTerminatedMutex.Unlock();
|
||||
wxThread::Sleep(200);
|
||||
|
||||
//signal the queue not empty condition since the ODMan thread will wait on the queue condition
|
||||
ODManager::Instance()->mQueueNotEmptyCondLock.Lock();
|
||||
ODManager::Instance()->mQueueNotEmptyCond->Signal();
|
||||
ODManager::Instance()->mQueueNotEmptyCondLock.Unlock();
|
||||
pMan->mQueueNotEmptyCondLock.Lock();
|
||||
pMan->mQueueNotEmptyCond->Signal();
|
||||
pMan->mQueueNotEmptyCondLock.Unlock();
|
||||
|
||||
ODManager::Instance()->mTerminatedMutex.Lock();
|
||||
pMan->mTerminatedMutex.Lock();
|
||||
}
|
||||
ODManager::Instance()->mTerminatedMutex.Unlock();
|
||||
pMan->mTerminatedMutex.Unlock();
|
||||
|
||||
|
||||
delete ODManager::Instance();
|
||||
delete pMan;
|
||||
//The above while loop waits for ODTasks to finish and the delete removes all tasks from the Queue.
|
||||
//This function is called from the main audacity event thread, so there should not be more requests for pMan
|
||||
}
|
||||
}
|
||||
|
||||
@ -572,10 +518,7 @@ void ODManager::UpdateQueues()
|
||||
ODWaveTrackTaskQueue* queue;
|
||||
queue = mQueues[i];
|
||||
|
||||
mQueuesMutex.Unlock();
|
||||
AddTask(queue->GetFrontTask());
|
||||
mQueuesMutex.Lock();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,7 @@ number of threads.
|
||||
|
||||
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_ODTASK_UPDATE, -1)
|
||||
|
||||
///wxstring compare function for sorting filenames with od
|
||||
int CompareODFileName(const wxString& first, const wxString& second);
|
||||
int CompareODFirstFileName(const wxString& first, const wxString& second);
|
||||
///wxstring compare function for sorting case, which is needed to load correctly.
|
||||
int CompareNoCaseFileName(const wxString& first, const wxString& second);
|
||||
/// A singleton that manages currently running Tasks on an arbitrary
|
||||
/// number of threads.
|
||||
@ -52,8 +50,13 @@ class ODWaveTrackTaskQueue;
|
||||
class ODManager
|
||||
{
|
||||
public:
|
||||
///Gets the singleton instance - this is a function pointer that points to one of the below two instance calls.
|
||||
///Note that it is not a member function pointer since it is a static function.
|
||||
static ODManager* (*Instance)();
|
||||
///Gets the singleton instance
|
||||
static ODManager* Instance();
|
||||
static ODManager* InstanceFirstTime();
|
||||
///Gets the singleton instance
|
||||
static ODManager* InstanceNormal();
|
||||
|
||||
///Kills the ODMananger Thread.
|
||||
static void Quit();
|
||||
@ -132,6 +135,8 @@ class ODManager
|
||||
///Remove references in our array to Tasks that have been completed/Schedule new ones
|
||||
void UpdateQueues();
|
||||
|
||||
//instance
|
||||
static ODManager* pMan;
|
||||
|
||||
//List of tracks and their active and inactive tasks.
|
||||
std::vector<ODWaveTrackTaskQueue*> mQueues;
|
||||
|
@ -110,7 +110,10 @@ void ODWaveTrackTaskQueue::AddTask(ODTask* task)
|
||||
mTracksMutex.Lock();
|
||||
for(int i=0;i<task->GetNumWaveTracks();i++)
|
||||
{
|
||||
//ODTask::GetWaveTrack is not threadsafe, but I think we are safe anyway, because the task isn't being run yet?
|
||||
//task->GetWaveTrack(i) may return NULL, but we handle it by checking before using.
|
||||
//The other worry that the WaveTrack returned and was deleted in the meantime is also
|
||||
//handled since mQueuesMutex is locked one up in the stack from here,
|
||||
//and WaveTrack deletion is bound to that.
|
||||
mTracks.push_back(task->GetWaveTrack(i));
|
||||
}
|
||||
|
||||
@ -165,7 +168,11 @@ void ODWaveTrackTaskQueue::MakeWaveTrackIndependent(WaveTrack* track)
|
||||
{
|
||||
task=mTasks[j]->Clone();
|
||||
task->AddWaveTrack(track);
|
||||
mTasksMutex.Unlock(); //AddNewTask assumes no locks.
|
||||
//AddNewTask requires us to relinquish this lock. However, it is safe because ODManager::MakeWaveTrackIndependent
|
||||
//has already locked the m_queuesMutex.
|
||||
mTasksMutex.Unlock();
|
||||
//AddNewTask locks the m_queuesMutex which is already locked by ODManager::MakeWaveTrackIndependent,
|
||||
//so we pass a boolean flag telling it not to lock again.
|
||||
ODManager::Instance()->AddNewTask(task,false);
|
||||
mTasksMutex.Lock();
|
||||
}
|
||||
@ -304,7 +311,7 @@ void ODWaveTrackTaskQueue::RemoveFrontTask()
|
||||
mTasksMutex.Unlock();
|
||||
}
|
||||
|
||||
///Schedules the front task for immediate execution
|
||||
///gets the front task for immediate execution
|
||||
ODTask* ODWaveTrackTaskQueue::GetFrontTask()
|
||||
{
|
||||
mTasksMutex.Lock();
|
||||
|
Loading…
x
Reference in New Issue
Block a user