mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-30 23:23:44 +02:00
Fix whitespace and comments in ODComputeSummaryTask and ODManager
This commit is contained in:
parent
f918edb36a
commit
0fac236e9a
@ -31,33 +31,29 @@ ODComputeSummaryTask::ODComputeSummaryTask()
|
||||
mMaxBlockFiles = 0;
|
||||
mComputedBlockFiles = 0;
|
||||
mHasUpdateRan=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ODTask* ODComputeSummaryTask::Clone()
|
||||
{
|
||||
ODComputeSummaryTask* clone = new ODComputeSummaryTask;
|
||||
clone->mDemandSample=GetDemandSample();
|
||||
return clone;
|
||||
|
||||
}
|
||||
|
||||
|
||||
///releases memory that the ODTask owns. Subclasses should override.
|
||||
void ODComputeSummaryTask::Terminate()
|
||||
{
|
||||
//The terminate cblock won't allow DoSomeInternal and this method to be run async, so this is thread-safe
|
||||
|
||||
//we are going to take things out of the array. But first deref them since we ref them when we put them in.
|
||||
|
||||
//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.
|
||||
mBlockFilesMutex.Lock();
|
||||
for(unsigned int i=0;i<mBlockFiles.size();i++)
|
||||
mBlockFiles[i]->Deref();
|
||||
mBlockFiles.clear();
|
||||
mBlockFilesMutex.Unlock();
|
||||
}
|
||||
|
||||
///Computes and writes the data for one BlockFile if it still has a refcount.
|
||||
}
|
||||
|
||||
///Computes and writes the data for one BlockFile if it still has a refcount.
|
||||
void ODComputeSummaryTask::DoSomeInternal()
|
||||
{
|
||||
if(mBlockFiles.size()<=0)
|
||||
@ -67,19 +63,18 @@ void ODComputeSummaryTask::DoSomeInternal()
|
||||
mPercentCompleteMutex.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ODPCMAliasBlockFile* bf;
|
||||
sampleCount blockStartSample;
|
||||
sampleCount blockEndSample;
|
||||
bool success =false;
|
||||
|
||||
|
||||
|
||||
mBlockFilesMutex.Lock();
|
||||
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
|
||||
{
|
||||
bf = mBlockFiles[0];
|
||||
|
||||
//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
|
||||
//the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
|
||||
if(bf->RefCount()>=2)
|
||||
@ -96,19 +91,18 @@ void ODComputeSummaryTask::DoSomeInternal()
|
||||
//because now there is less work to do.
|
||||
mMaxBlockFiles--;
|
||||
}
|
||||
|
||||
|
||||
//Release the refcount we placed on it.
|
||||
bf->Deref();
|
||||
//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.
|
||||
|
||||
//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();
|
||||
|
||||
|
||||
|
||||
//upddate the gui for all associated blocks. It doesn't matter that we're hitting more wavetracks then we should
|
||||
//because this loop runs a number of times equal to the number of tracks, they probably are getting processed in
|
||||
//the next iteration at the same sample window.
|
||||
@ -119,28 +113,26 @@ void ODComputeSummaryTask::DoSomeInternal()
|
||||
mWaveTracks[i]->AddInvalidRegion(blockStartSample,blockEndSample);
|
||||
}
|
||||
mWaveTrackMutex.Unlock();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mBlockFilesMutex.Unlock();
|
||||
|
||||
|
||||
//update percentage complete.
|
||||
CalculatePercentComplete();
|
||||
}
|
||||
|
||||
///compute the next time we should take a break in terms of overall percentage.
|
||||
///We want to do a constant number of blockfiles.
|
||||
///We want to do a constant number of blockfiles.
|
||||
float ODComputeSummaryTask::ComputeNextWorkUntilPercentageComplete()
|
||||
{
|
||||
if(mMaxBlockFiles==0)
|
||||
return 1.0;
|
||||
|
||||
|
||||
float nextPercent;
|
||||
mPercentCompleteMutex.Lock();
|
||||
nextPercent=mPercentComplete + ((float)kNumBlockFilesPerDoSome/(mMaxBlockFiles+1));
|
||||
mPercentCompleteMutex.Unlock();
|
||||
|
||||
|
||||
return nextPercent;
|
||||
}
|
||||
|
||||
@ -149,7 +141,7 @@ void ODComputeSummaryTask::MarkUpdateRan()
|
||||
mHasUpdateRanMutex.Lock();
|
||||
mHasUpdateRan=true;
|
||||
mHasUpdateRanMutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool ODComputeSummaryTask::HasUpdateRan()
|
||||
{
|
||||
@ -172,14 +164,14 @@ void ODComputeSummaryTask::CalculatePercentComplete()
|
||||
mPercentCompleteMutex.Unlock();
|
||||
}
|
||||
|
||||
///by default creates the order of the wavetrack to load.
|
||||
///creates the order of the wavetrack to load.
|
||||
///by default left to right, or frome the point the user has clicked.
|
||||
void ODComputeSummaryTask::Update()
|
||||
{
|
||||
|
||||
std::vector<ODPCMAliasBlockFile*> tempBlocks;
|
||||
|
||||
|
||||
mWaveTrackMutex.Lock();
|
||||
|
||||
|
||||
for(size_t j=0;j<mWaveTracks.size();j++)
|
||||
{
|
||||
if(mWaveTracks[j])
|
||||
@ -187,27 +179,27 @@ void ODComputeSummaryTask::Update()
|
||||
WaveClip *clip;
|
||||
BlockArray *blocks;
|
||||
Sequence *seq;
|
||||
|
||||
|
||||
//gather all the blockfiles that we should process in the wavetrack.
|
||||
WaveClipList::compatibility_iterator node = mWaveTracks[j]->GetClipIterator();
|
||||
|
||||
|
||||
while(node) {
|
||||
clip = node->GetData();
|
||||
seq = clip->GetSequence();
|
||||
//This lock may be way too big since the whole file is one sequence.
|
||||
//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.
|
||||
//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 insertCursor;
|
||||
|
||||
|
||||
insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n)
|
||||
|
||||
|
||||
for(i=0; i<(int)blocks->GetCount(); i++)
|
||||
{
|
||||
//if there is data but no summary, this blockfile needs summarizing.
|
||||
@ -216,59 +208,59 @@ void ODComputeSummaryTask::Update()
|
||||
blocks->Item(i)->f->Ref();
|
||||
((ODPCMAliasBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start);
|
||||
((ODPCMAliasBlockFile*)blocks->Item(i)->f)->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate()));
|
||||
|
||||
|
||||
//these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
|
||||
while(insertCursor<(int)tempBlocks.size()&&
|
||||
(sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) <
|
||||
while(insertCursor<(int)tempBlocks.size()&&
|
||||
(sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) <
|
||||
(sampleCount)(((ODPCMAliasBlockFile*)blocks->Item(i)->f)->GetStart()+((ODPCMAliasBlockFile*)blocks->Item(i)->f)->GetClipOffset()))
|
||||
insertCursor++;
|
||||
|
||||
|
||||
tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODPCMAliasBlockFile*)blocks->Item(i)->f);
|
||||
}
|
||||
}
|
||||
}
|
||||
seq->UnlockDeleteUpdateMutex();
|
||||
node = node->GetNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
mWaveTrackMutex.Unlock();
|
||||
|
||||
|
||||
//get the new order.
|
||||
mBlockFilesMutex.Lock();
|
||||
OrderBlockFiles(tempBlocks);
|
||||
mBlockFilesMutex.Unlock();
|
||||
|
||||
|
||||
MarkUpdateRan();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///Orders the input as either On-Demand or default layered order.
|
||||
///Computes the summary calculation queue order of the blockfiles
|
||||
void ODComputeSummaryTask::OrderBlockFiles(std::vector<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();
|
||||
//TODO: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
|
||||
//(which the user sets by clicking.)
|
||||
//(which the user sets by clicking.)
|
||||
//Note that this code assumes that the array is sorted in time.
|
||||
|
||||
|
||||
//find the startpoint
|
||||
sampleCount processStartSample = GetDemandSample();
|
||||
sampleCount processStartSample = GetDemandSample();
|
||||
for(int i= ((int)unorderedBlocks.size())-1;i>= 0;i--)
|
||||
{
|
||||
//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(unorderedBlocks[i]->RefCount()>=2)
|
||||
{
|
||||
//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 ||
|
||||
if(mBlockFiles.size() &&
|
||||
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
|
||||
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
|
||||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart())
|
||||
)
|
||||
{
|
||||
@ -289,5 +281,4 @@ void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &un
|
||||
unorderedBlocks[i]->Deref();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -16,9 +16,6 @@ updating the ODPCMAliasBlockFile and the GUI of the newly available data.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __AUDACITY_ODComputeSummaryTask__
|
||||
#define __AUDACITY_ODComputeSummaryTask__
|
||||
|
||||
@ -54,10 +51,8 @@ class ODComputeSummaryTask:public ODTask
|
||||
|
||||
///releases memory that the ODTask owns. Subclasses should override.
|
||||
virtual void Terminate();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
///recalculates the percentage complete.
|
||||
virtual void CalculatePercentComplete();
|
||||
|
||||
@ -78,17 +73,10 @@ protected:
|
||||
//mBlockFiles is touched on several threads- the OD terminate thread, and the task thread, so we need to mutex it.
|
||||
ODLock mBlockFilesMutex;
|
||||
std::vector<ODPCMAliasBlockFile*> mBlockFiles;
|
||||
|
||||
|
||||
int mMaxBlockFiles;
|
||||
int mComputedBlockFiles;
|
||||
|
||||
|
||||
|
||||
ODLock mHasUpdateRanMutex;
|
||||
bool mHasUpdateRan;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
\file ODManager.cpp
|
||||
\brief Singleton ODManager class. Is the bridge between client side
|
||||
ODTask requests and internals.
|
||||
ODTask requests and internals.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
@ -28,11 +28,11 @@ ODTask requests and internals.
|
||||
ODLock gODInitedMutex;
|
||||
bool gManagerCreated=false;
|
||||
bool gPause=false; //to be loaded in and used with Pause/Resume before ODMan init.
|
||||
/// a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
/// 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
|
||||
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);
|
||||
@ -42,7 +42,7 @@ ODLock sLibSndFileMutex;
|
||||
|
||||
DEFINE_EVENT_TYPE(EVT_ODTASK_UPDATE)
|
||||
|
||||
//using this with wxStringArray::Sort will give you a list that
|
||||
//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.
|
||||
int CompareNoCaseFileName(const wxString& first, const wxString& second)
|
||||
@ -67,7 +67,7 @@ ODManager::ODManager()
|
||||
mTerminate = false;
|
||||
mTerminated = false;
|
||||
mPause= gPause;
|
||||
|
||||
|
||||
//must set up the queue condition
|
||||
mQueueNotEmptyCond = new ODCondition(&mQueueNotEmptyCondLock);
|
||||
}
|
||||
@ -83,17 +83,15 @@ ODManager::~ODManager()
|
||||
delete mQueueNotEmptyCond;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///Adds a task to running queue. Thread-safe.
|
||||
void ODManager::AddTask(ODTask* task)
|
||||
{
|
||||
mTasksMutex.Lock();
|
||||
mTasks.push_back(task);
|
||||
mTasksMutex.Unlock();
|
||||
//signal the queue not empty condition.
|
||||
//signal the queue not empty condition.
|
||||
bool paused;
|
||||
|
||||
|
||||
mPauseLock.Lock();
|
||||
paused=mPause;
|
||||
mPauseLock.Unlock();
|
||||
@ -103,13 +101,12 @@ void ODManager::AddTask(ODTask* task)
|
||||
if(!paused)
|
||||
mQueueNotEmptyCond->Signal();
|
||||
mQueueNotEmptyCondLock.Unlock();
|
||||
|
||||
}
|
||||
|
||||
void ODManager::SignalTaskQueueLoop()
|
||||
{
|
||||
bool paused;
|
||||
|
||||
|
||||
mPauseLock.Lock();
|
||||
paused=mPause;
|
||||
mPauseLock.Unlock();
|
||||
@ -154,7 +151,7 @@ void ODManager::AddNewTask(ODTask* task, bool lockMutex)
|
||||
if(mQueues[i]->ContainsWaveTrack(task->GetWaveTrack(0)))
|
||||
queue=mQueues[i];
|
||||
}
|
||||
|
||||
|
||||
if(queue)
|
||||
{
|
||||
//Add it to the existing queue but keep the lock since this reference can be deleted.
|
||||
@ -171,12 +168,11 @@ void ODManager::AddNewTask(ODTask* task, bool lockMutex)
|
||||
mQueues.push_back(queue);
|
||||
if(lockMutex)
|
||||
mQueuesMutex.Unlock();
|
||||
|
||||
|
||||
AddTask(task);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//that switches out the mutex/null check.
|
||||
ODManager* ODManager::InstanceFirstTime()
|
||||
{
|
||||
@ -188,10 +184,10 @@ ODManager* ODManager::InstanceFirstTime()
|
||||
gManagerCreated = true;
|
||||
}
|
||||
gODInitedMutex.Unlock();
|
||||
|
||||
|
||||
//change the accessor function to use the quicker method.
|
||||
Instance = &(ODManager::InstanceNormal);
|
||||
|
||||
|
||||
return pMan;
|
||||
}
|
||||
|
||||
@ -215,15 +211,15 @@ void ODManager::Init()
|
||||
{
|
||||
mCurrentThreads = 0;
|
||||
mMaxThreads = 5;
|
||||
|
||||
|
||||
// wxLogDebug(wxT("Initializing ODManager...Creating manager thread\n"));
|
||||
ODManagerHelperThread* startThread = new ODManagerHelperThread;
|
||||
|
||||
|
||||
// startThread->SetPriority(0);//default of 50.
|
||||
startThread->Create();
|
||||
// printf("starting thread from init\n");
|
||||
startThread->Run();
|
||||
|
||||
|
||||
// printf("started thread from init\n");
|
||||
//destruction of thread is taken care of by thread library
|
||||
}
|
||||
@ -237,12 +233,12 @@ void ODManager::DecrementCurrentThreads()
|
||||
|
||||
///Main loop for managing threads and tasks.
|
||||
void ODManager::Start()
|
||||
{
|
||||
{
|
||||
ODTaskThread* thread;
|
||||
bool tasksInArray;
|
||||
bool paused;
|
||||
int numQueues=0;
|
||||
|
||||
|
||||
mNeedsDraw=0;
|
||||
|
||||
//wxLog calls not threadsafe. are printfs? thread-messy for sure, but safe?
|
||||
@ -254,54 +250,52 @@ void ODManager::Start()
|
||||
{
|
||||
mTerminateMutex.Unlock();
|
||||
// printf("ODManager thread running \n");
|
||||
|
||||
|
||||
//we should look at our WaveTrack queues to see if we can process a new task to the running queue.
|
||||
UpdateQueues();
|
||||
|
||||
|
||||
//start some threads if necessary
|
||||
|
||||
|
||||
mTasksMutex.Lock();
|
||||
tasksInArray = mTasks.size()>0;
|
||||
mTasksMutex.Unlock();
|
||||
mCurrentThreadsMutex.Lock();
|
||||
|
||||
|
||||
mPauseLock.Lock();
|
||||
paused=mPause;
|
||||
mPauseLock.Unlock();
|
||||
|
||||
|
||||
// keep adding tasks if there is work to do, up to the limit.
|
||||
while(!paused && tasksInArray && (mCurrentThreads < mMaxThreads))
|
||||
{
|
||||
mCurrentThreads++;
|
||||
mCurrentThreadsMutex.Unlock();
|
||||
//remove the head
|
||||
|
||||
|
||||
//detach a new thread.
|
||||
thread = new ODTaskThread(mTasks[0]);//task);
|
||||
|
||||
// thread->SetPriority(10);//default is 50.
|
||||
//thread->SetPriority(10);//default is 50.
|
||||
thread->Create();
|
||||
thread->Run();
|
||||
|
||||
mTasks.erase(mTasks.begin());
|
||||
|
||||
mTasks.erase(mTasks.begin());
|
||||
tasksInArray = mTasks.size()>0;
|
||||
|
||||
|
||||
mTasksMutex.Unlock();
|
||||
|
||||
|
||||
mCurrentThreadsMutex.Lock();
|
||||
}
|
||||
|
||||
mCurrentThreadsMutex.Unlock();
|
||||
//use a conditon variable to block here instead of a sleep.
|
||||
//use a conditon variable to block here instead of a sleep.
|
||||
|
||||
// JKC: If there are no tasks ready to run, or we're paused then
|
||||
// JKC: If there are no tasks ready to run, or we're paused then
|
||||
// we wait for there to be tasks in the queue.
|
||||
mQueueNotEmptyCondLock.Lock();
|
||||
if( (!tasksInArray) || paused)
|
||||
mQueueNotEmptyCond->Wait();
|
||||
mQueueNotEmptyCondLock.Unlock();
|
||||
|
||||
//if there is some ODTask running, then there will be something in the queue. If so then redraw to show progress
|
||||
mQueueNotEmptyCondLock.Unlock();
|
||||
|
||||
//if there is some ODTask running, then there will be something in the queue. If so then redraw to show progress
|
||||
mQueuesMutex.Lock();
|
||||
mNeedsDraw += mQueues.size()>0?1:0;
|
||||
numQueues=mQueues.size();
|
||||
@ -319,15 +313,15 @@ void ODManager::Start()
|
||||
if(proj)
|
||||
proj->AddPendingEvent( event );
|
||||
AudacityProject::AllProjectsDeleteUnlock();
|
||||
}
|
||||
}
|
||||
mTerminateMutex.Lock();
|
||||
}
|
||||
mTerminateMutex.Unlock();
|
||||
|
||||
|
||||
mTerminatedMutex.Lock();
|
||||
mTerminated=true;
|
||||
mTerminatedMutex.Unlock();
|
||||
|
||||
|
||||
//wxLogDebug Not thread safe.
|
||||
//printf("ODManager thread terminating\n");
|
||||
|
||||
@ -343,7 +337,7 @@ void ODManager::Pause(bool pause)
|
||||
pMan->mPauseLock.Lock();
|
||||
pMan->mPause = pause;
|
||||
pMan->mPauseLock.Unlock();
|
||||
|
||||
|
||||
//we should check the queue again.
|
||||
pMan->mQueueNotEmptyCondLock.Lock();
|
||||
pMan->mQueueNotEmptyCond->Signal();
|
||||
@ -367,13 +361,15 @@ void ODManager::Quit()
|
||||
pMan->mTerminateMutex.Lock();
|
||||
pMan->mTerminate = true;
|
||||
pMan->mTerminateMutex.Unlock();
|
||||
|
||||
|
||||
//This 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
|
||||
pMan->mTerminatedMutex.Lock();
|
||||
while(!pMan->mTerminated)
|
||||
{
|
||||
pMan->mTerminatedMutex.Unlock();
|
||||
wxThread::Sleep(200);
|
||||
|
||||
|
||||
//signal the queue not empty condition since the ODMan thread will wait on the queue condition
|
||||
pMan->mQueueNotEmptyCondLock.Lock();
|
||||
pMan->mQueueNotEmptyCond->Signal();
|
||||
@ -382,15 +378,11 @@ void ODManager::Quit()
|
||||
pMan->mTerminatedMutex.Lock();
|
||||
}
|
||||
pMan->mTerminatedMutex.Unlock();
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
///removes a wavetrack and notifies its associated tasks to stop using its reference.
|
||||
|
||||
///removes a wavetrack and notifies its associated tasks to stop using its reference.
|
||||
void ODManager::RemoveWaveTrack(WaveTrack* track)
|
||||
{
|
||||
mQueuesMutex.Lock();
|
||||
@ -411,7 +403,7 @@ void ODManager::ReplaceWaveTrack(WaveTrack* oldTrack,WaveTrack* newTrack)
|
||||
mQueues[i]->ReplaceWaveTrack(oldTrack,newTrack);
|
||||
}
|
||||
mQueuesMutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
///if it shares a queue/task, creates a new queue/task for the track, and removes it from any previously existing tasks.
|
||||
void ODManager::MakeWaveTrackIndependent(WaveTrack* track)
|
||||
@ -430,24 +422,22 @@ void ODManager::MakeWaveTrackIndependent(WaveTrack* track)
|
||||
owner->MakeWaveTrackIndependent(track);
|
||||
|
||||
mQueuesMutex.Unlock();
|
||||
|
||||
}
|
||||
|
||||
///attach the track in question to another, already existing track's queues and tasks. Remove the task/tracks.
|
||||
///only works if both tracks exist. Sets needODUpdate flag for the task. This is complicated and will probably need
|
||||
///better design in the future.
|
||||
///@return returns success. Some ODTask conditions require that the tasks finish before merging.
|
||||
///e.g. they have different effects being processed at the same time.
|
||||
///@return returns success. Some ODTask conditions require that the tasks finish before merging.
|
||||
///e.g. they have different effects being processed at the same time.
|
||||
bool ODManager::MakeWaveTrackDependent(WaveTrack* dependentTrack,WaveTrack* masterTrack)
|
||||
{
|
||||
|
||||
//First, check to see if the task lists are mergeable. If so, we can simply add this track to the other task and queue,
|
||||
//First, check to see if the task lists are mergeable. If so, we can simply add this track to the other task and queue,
|
||||
//then delete this one.
|
||||
ODWaveTrackTaskQueue* masterQueue=NULL;
|
||||
ODWaveTrackTaskQueue* dependentQueue=NULL;
|
||||
unsigned int dependentIndex;
|
||||
bool canMerge = false;
|
||||
|
||||
|
||||
mQueuesMutex.Lock();
|
||||
for(unsigned int i=0;i<mQueues.size();i++)
|
||||
{
|
||||
@ -465,17 +455,16 @@ bool ODManager::MakeWaveTrackDependent(WaveTrack* dependentTrack,WaveTrack* mast
|
||||
if(masterQueue&&dependentQueue)
|
||||
canMerge=masterQueue->CanMergeWith(dependentQueue);
|
||||
|
||||
|
||||
//otherwise we need to let dependentTrack's queue live on. We'll have to wait till the conflicting tasks are done.
|
||||
if(!canMerge)
|
||||
{
|
||||
{
|
||||
mQueuesMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//then we add dependentTrack to the masterTrack's queue - this will allow future ODScheduling to affect them together.
|
||||
//this sets the NeedODUpdateFlag since we don't want the head task to finish without haven't dealt with the depednent
|
||||
masterQueue->MergeWaveTrack(dependentTrack);
|
||||
|
||||
|
||||
//finally remove the dependent track
|
||||
mQueues.erase(mQueues.begin()+dependentIndex);
|
||||
mQueuesMutex.Unlock();
|
||||
@ -495,9 +484,8 @@ void ODManager::DemandTrackUpdate(WaveTrack* track, double seconds)
|
||||
mQueues[i]->DemandTrackUpdate(track,seconds);
|
||||
}
|
||||
mQueuesMutex.Unlock();
|
||||
|
||||
}
|
||||
|
||||
|
||||
///remove tasks from ODWaveTrackTaskQueues that have been done. Schedules new ones if they exist
|
||||
///Also remove queues that have become empty.
|
||||
void ODManager::UpdateQueues()
|
||||
@ -505,7 +493,6 @@ void ODManager::UpdateQueues()
|
||||
mQueuesMutex.Lock();
|
||||
for(unsigned int i=0;i<mQueues.size();i++)
|
||||
{
|
||||
|
||||
if(mQueues[i]->IsFrontTaskComplete())
|
||||
{
|
||||
//this should delete and remove the front task instance.
|
||||
@ -517,11 +504,11 @@ void ODManager::UpdateQueues()
|
||||
//so get a temp.
|
||||
ODWaveTrackTaskQueue* queue;
|
||||
queue = mQueues[i];
|
||||
|
||||
|
||||
AddTask(queue->GetFrontTask());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//if the queue is empty delete it.
|
||||
if(mQueues[i]->IsEmpty())
|
||||
{
|
||||
@ -531,25 +518,24 @@ void ODManager::UpdateQueues()
|
||||
}
|
||||
}
|
||||
mQueuesMutex.Unlock();
|
||||
|
||||
}
|
||||
|
||||
//static
|
||||
///sets a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
//static
|
||||
///sets a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
void ODManager::MarkLoadedODFlag()
|
||||
{
|
||||
sHasLoadedOD = true;
|
||||
}
|
||||
|
||||
//static
|
||||
///resets a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
}
|
||||
|
||||
//static
|
||||
///resets a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
void ODManager::UnmarkLoadedODFlag()
|
||||
{
|
||||
sHasLoadedOD = false;
|
||||
}
|
||||
|
||||
//static
|
||||
///returns a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
|
||||
//static
|
||||
///returns a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
bool ODManager::HasLoadedODFlag()
|
||||
{
|
||||
return sHasLoadedOD;
|
||||
@ -576,12 +562,12 @@ float ODManager::GetOverallPercentComplete()
|
||||
total+=mQueues[i]->GetFrontTask()->PercentComplete();
|
||||
}
|
||||
mQueuesMutex.Unlock();
|
||||
|
||||
|
||||
//avoid div by zero and be thread smart.
|
||||
int totalTasks = GetTotalNumTasks();
|
||||
return (float) total/(totalTasks>0?totalTasks:1);
|
||||
}
|
||||
|
||||
|
||||
///Get Total Number of Tasks.
|
||||
int ODManager::GetTotalNumTasks()
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
ODManager.h
|
||||
|
||||
|
||||
Created by Michael Chinen (mchinen) on 6/8/08
|
||||
Audacity(R) is copyright (c) 1999-2008 Audacity Team.
|
||||
License: GPL v2. See License.txt.
|
||||
@ -11,39 +11,32 @@
|
||||
******************************************************************//**
|
||||
|
||||
\class ODManager
|
||||
\brief A singleton that manages currently running Tasks on an arbitrary
|
||||
\brief A singleton that manages currently running Tasks on an arbitrary
|
||||
number of threads.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __AUDACITY_ODMANAGER__
|
||||
#define __AUDACITY_ODMANAGER__
|
||||
|
||||
#include <vector>
|
||||
#include "ODTask.h"
|
||||
#include "ODTaskThread.h"
|
||||
#include <wx/thread.h>
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#ifdef __WXMAC__
|
||||
|
||||
// On Mac OS X, it's better not to use the wxThread class.
|
||||
// We use our own implementation based on pthreads instead.
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#endif //__WXMAC__
|
||||
|
||||
|
||||
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_ODTASK_UPDATE, -1)
|
||||
|
||||
///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
|
||||
/// A singleton that manages currently running Tasks on an arbitrary
|
||||
/// number of threads.
|
||||
class WaveTrack;
|
||||
class ODWaveTrackTaskQueue;
|
||||
@ -57,61 +50,61 @@ class ODManager
|
||||
static ODManager* InstanceFirstTime();
|
||||
///Gets the singleton instance
|
||||
static ODManager* InstanceNormal();
|
||||
|
||||
|
||||
///Kills the ODMananger Thread.
|
||||
static void Quit();
|
||||
|
||||
static void Quit();
|
||||
|
||||
///changes the tasks associated with this Waveform to process the task from a different point in the track
|
||||
void DemandTrackUpdate(WaveTrack* track, double seconds);
|
||||
|
||||
|
||||
///Reduces the count of current threads running. Meant to be called when ODTaskThreads end in their own threads. Thread-safe.
|
||||
void DecrementCurrentThreads();
|
||||
|
||||
///Adds a wavetrack, creates a queue member.
|
||||
|
||||
///Adds a wavetrack, creates a queue member.
|
||||
void AddNewTask(ODTask* task, bool lockMutex=true);
|
||||
|
||||
|
||||
///Wakes the queue loop up by signalling its condition variable.
|
||||
void SignalTaskQueueLoop();
|
||||
|
||||
///removes a wavetrack and notifies its associated tasks to stop using its reference.
|
||||
|
||||
///removes a wavetrack and notifies its associated tasks to stop using its reference.
|
||||
void RemoveWaveTrack(WaveTrack* track);
|
||||
|
||||
|
||||
///if it shares a queue/task, creates a new queue/task for the track, and removes it from any previously existing tasks.
|
||||
void MakeWaveTrackIndependent(WaveTrack* track);
|
||||
|
||||
|
||||
///attach the track in question to another, already existing track's queues and tasks. Remove the task/tracks.
|
||||
///Returns success if it was possible.. Some ODTask conditions make it impossible until the Tasks finish.
|
||||
bool MakeWaveTrackDependent(WaveTrack* dependentTrack,WaveTrack* masterTrack);
|
||||
|
||||
|
||||
///replace the wavetrack whose wavecache the gui watches for updates
|
||||
void ReplaceWaveTrack(WaveTrack* oldTrack,WaveTrack* newTrack);
|
||||
|
||||
void ReplaceWaveTrack(WaveTrack* oldTrack,WaveTrack* newTrack);
|
||||
|
||||
///Adds a task to the running queue. Threas-safe.
|
||||
void AddTask(ODTask* task);
|
||||
|
||||
|
||||
void RemoveTaskIfInQueue(ODTask* task);
|
||||
|
||||
///sets a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
|
||||
///sets a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
static void MarkLoadedODFlag();
|
||||
|
||||
///resets a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
|
||||
///resets a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
static void UnmarkLoadedODFlag();
|
||||
|
||||
///returns a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
|
||||
///returns a flag that is set if we have loaded some OD blockfiles from PCM.
|
||||
static bool HasLoadedODFlag();
|
||||
|
||||
|
||||
///returns whether or not the singleton instance was created yet
|
||||
static bool IsInstanceCreated();
|
||||
|
||||
|
||||
///fills in the status bar message for a given track
|
||||
void FillTipForWaveTrack( WaveTrack * t, const wxChar ** ppTip );
|
||||
|
||||
|
||||
///Gets the total percent complete for all tasks combined.
|
||||
float GetOverallPercentComplete();
|
||||
|
||||
|
||||
///Get Total Number of Tasks.
|
||||
int GetTotalNumTasks();
|
||||
|
||||
|
||||
//Pause/unpause all OD Tasks. Does not occur immediately.
|
||||
static void Pause(bool pause = true);
|
||||
static void Resume();
|
||||
@ -120,7 +113,7 @@ class ODManager
|
||||
static void UnlockLibSndFileMutex();
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
//private constructor - Singleton.
|
||||
ODManager();
|
||||
@ -131,47 +124,46 @@ class ODManager
|
||||
|
||||
///Start the main loop for the manager.
|
||||
void Start();
|
||||
|
||||
|
||||
///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;
|
||||
ODLock mQueuesMutex;
|
||||
|
||||
|
||||
//List of current Task to do.
|
||||
std::vector<ODTask*> mTasks;
|
||||
//mutex for above variable
|
||||
ODLock mTasksMutex;
|
||||
|
||||
|
||||
//global pause switch for OD
|
||||
volatile bool mPause;
|
||||
ODLock mPauseLock;
|
||||
|
||||
volatile int mNeedsDraw;
|
||||
|
||||
|
||||
///Number of threads currently running. Accessed thru multiple threads
|
||||
volatile int mCurrentThreads;
|
||||
//mutex for above variable
|
||||
ODLock mCurrentThreadsMutex;
|
||||
|
||||
|
||||
|
||||
///Maximum number of threads allowed out.
|
||||
int mMaxThreads;
|
||||
|
||||
|
||||
volatile bool mTerminate;
|
||||
ODLock mTerminateMutex;
|
||||
|
||||
|
||||
volatile bool mTerminated;
|
||||
ODLock mTerminatedMutex;
|
||||
|
||||
|
||||
//for the queue not empty comdition
|
||||
ODLock mQueueNotEmptyCondLock;
|
||||
ODCondition* mQueueNotEmptyCond;
|
||||
|
||||
|
||||
#ifdef __WXMAC__
|
||||
|
||||
// On Mac OS X, it's better not to use the wxThread class.
|
||||
@ -201,34 +193,30 @@ class ODManagerHelperThread {
|
||||
ODManagerHelperThread *th = (ODManagerHelperThread *)p;
|
||||
/* return (void *) */th->Entry();
|
||||
}
|
||||
|
||||
|
||||
///Specifies the priority the thread will run at. Currently doesn't work.
|
||||
///@param priority value from 0 (min priority) to 100 (max priority)
|
||||
void SetPriority(int priority)
|
||||
{
|
||||
mPriority=priority;
|
||||
}
|
||||
|
||||
|
||||
void Run() {
|
||||
pthread_create(&mThread, NULL, callback, this);
|
||||
}
|
||||
private:
|
||||
bool mDestroy;
|
||||
pthread_t mThread;
|
||||
|
||||
int mPriority;
|
||||
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class ODManagerHelperThread : public wxThread
|
||||
class ODManagerHelperThread : public wxThread
|
||||
{
|
||||
public:
|
||||
///Constructs a ODTaskThread
|
||||
///@param task the task to be launched as an
|
||||
///@param task the task to be launched as an
|
||||
ODManagerHelperThread(): wxThread(){}
|
||||
|
||||
|
||||
protected:
|
||||
///Executes a part of the task
|
||||
void *Entry()
|
||||
@ -236,14 +224,9 @@ class ODManagerHelperThread {
|
||||
ODManager::Instance()->Start();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //__WXMAC__
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user