audacia/src/ondemand/ODManager.h

247 lines
7.3 KiB
C++

/**********************************************************************
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.
******************************************************************//**
\class ODManager
\brief A singleton that manages currently running Tasks on an arbitrary
number of threads.
*//*******************************************************************/
#ifndef __AUDACITY_ODMANAGER__
#define __AUDACITY_ODMANAGER__
#include <vector>
#include "ODTaskThread.h"
#include <wx/event.h> // for DECLARE_EXPORTED_EVENT_TYPE
#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__
// This event is posted to the application
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_ODTASK_UPDATE, wxCommandEvent);
///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.
class TranslatableString;
class Track;
class WaveTrack;
class ODWaveTrackTaskQueue;
class ODManager final
{
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.
///the function pointer swapping is valid as long as the initial calls only happen from the main thread.
static ODManager* (*Instance)();
///Gets the singleton instance
static ODManager* InstanceFirstTime();
///Gets the singleton instance
static ODManager* InstanceNormal();
///Kills the ODMananger Thread.
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.
void AddNewTask(std::unique_ptr<ODTask> &&mtask, bool lockMutex=true);
///Wakes the queue loop up by signalling its condition variable.
void SignalTaskQueueLoop();
///if it shares a queue/task, creates a NEW queue/task for the track, and removes it from any previously existing tasks.
void MakeWaveTrackIndependent( const std::shared_ptr< 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(
const std::shared_ptr< WaveTrack > &dependentTrack,
WaveTrack* masterTrack
);
///if oldTrack is being watched,
///replace the wavetrack whose wavecache the gui watches for updates
void ReplaceWaveTrack(Track *oldTrack,
const std::shared_ptr< Track > &newTrack);
///Adds a task to the running queue. Thread-safe.
void AddTask(ODTask* task);
void RemoveTaskIfInQueue(ODTask* task);
///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.
static void UnmarkLoadedODFlag();
///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( const WaveTrack * t, TranslatableString &tip );
///Gets the total percent complete for all tasks combined.
float GetOverallPercentComplete();
///Get Total Number of Tasks.
int GetTotalNumTasks();
// RAII object for pausing and resuming..
class Pauser
{
//Pause/unpause all OD Tasks. Does not occur immediately.
static void Pause(bool pause = true);
static void Resume();
public:
Pauser() { Pause(); }
~Pauser() { Resume(); }
Pauser(const Pauser&) PROHIBITED;
Pauser &operator= (const Pauser&) PROHIBITED;
};
protected:
//private constructor - Singleton.
ODManager();
//private constructor - DELETE with static method Quit()
friend std::default_delete < ODManager > ;
~ODManager();
///Launches a thread for the manager and starts accepting Tasks.
void Init();
///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 std::unique_ptr<ODManager> pMan;
//List of tracks and their active and inactive tasks.
std::vector<std::unique_ptr<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;
std::unique_ptr<ODCondition> mQueueNotEmptyCond;
#ifdef __WXMAC__
// On Mac OS X, it's better not to use the wxThread class.
// We use our own implementation based on pthreads instead.
class ODManagerHelperThread {
public:
typedef int ExitCode;
ODManagerHelperThread() { mDestroy = false; mThread = NULL; }
/* ExitCode*/ void Entry(){
ODManager::Instance()->Start();
}
void Create() {}
void Delete() {
mDestroy = true;
pthread_join(mThread, NULL);
}
bool TestDestroy() { return mDestroy; }
void Sleep(int ms) {
struct timespec spec;
spec.tv_sec = 0;
spec.tv_nsec = ms * 1000 * 1000;
nanosleep(&spec, NULL);
}
static void *callback(void *p) {
ODManagerHelperThread *th = (ODManagerHelperThread *)p;
/* return (void *) */th->Entry();
return NULL;
}
///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 final : public wxThread
{
public:
///Constructs an ODManagerHelperThread
///@param task the task to be launched as an
ODManagerHelperThread(): wxThread(){}
protected:
///Executes a part of the task
void *Entry()
{
ODManager::Instance()->Start();
return NULL;
}
};
#endif //__WXMAC__
};
#endif