Now using a separate QSemaphore to limit the number of tasks in the queue of the QThreadPool. Instead of starting exactly as many task as there are threads in the pool and adding a new task only after a running one finished, we will now keep a fixed number of tasks in the queue (currently hardcoded to 32). Since there always will be more tasks left in the queue than there are threads in the pool, we ensure that no thread will ever become idle. Might be slightly faster than the "old" approach.

This commit is contained in:
LoRd_MuldeR 2012-05-25 02:24:44 +02:00
parent 61dc8e34c4
commit a291771153
10 changed files with 760 additions and 751 deletions

View File

@ -72,10 +72,10 @@ if not "%LAMEXP_ERROR%"=="0" (
GOTO:EOF GOTO:EOF
) )
REM ------------------------------------------ REM ------------------------------------------
set "OUT_FILE=%OUT_PATH%\..\LameXP.%ISO_DATE%.%LAMEXP_CONFIG:_=-%.Build-%VER_LAMEXP_BUILD%" set "OUT_FILE=%OUT_PATH%\..\%VER_LAMEXP_BASENAME%.%ISO_DATE%.%LAMEXP_CONFIG:_=-%.Build-%VER_LAMEXP_BUILD%"
for /L %%n in (1, 1, 99) do ( for /L %%n in (1, 1, 99) do (
if exist "!OUT_FILE!.exe" set "OUT_FILE=%OUT_PATH%\..\LameXP.%ISO_DATE%.%LAMEXP_CONFIG:_=-%.Build-%VER_LAMEXP_BUILD%.Update-%%n" if exist "!OUT_FILE!.exe" set "OUT_FILE=%OUT_PATH%\..\%VER_LAMEXP_BASENAME%.%ISO_DATE%.%LAMEXP_CONFIG:_=-%.Build-%VER_LAMEXP_BUILD%.Update-%%n"
if exist "!OUT_FILE!.zip" set "OUT_FILE=%OUT_PATH%\..\LameXP.%ISO_DATE%.%LAMEXP_CONFIG:_=-%.Build-%VER_LAMEXP_BUILD%.Update-%%n" if exist "!OUT_FILE!.zip" set "OUT_FILE=%OUT_PATH%\..\%VER_LAMEXP_BASENAME%.%ISO_DATE%.%LAMEXP_CONFIG:_=-%.Build-%VER_LAMEXP_BUILD%.Update-%%n"
) )
REM ------------------------------------------ REM ------------------------------------------
REM :: DELETE OLD OUTPUT FILE :: REM :: DELETE OLD OUTPUT FILE ::

View File

@ -7,6 +7,7 @@ set "VER_LAMEXP_MINOR_LO="
set "VER_LAMEXP_BUILD=" set "VER_LAMEXP_BUILD="
set "VER_LAMEXP_TYPE=" set "VER_LAMEXP_TYPE="
set "VER_LAMEXP_PATCH=" set "VER_LAMEXP_PATCH="
set "VER_LAMEXP_BASENAME="
REM ------------------------------------------ REM ------------------------------------------
for /f "tokens=2,*" %%s in (%~dp0\..\..\src\Config.h) do ( for /f "tokens=2,*" %%s in (%~dp0\..\..\src\Config.h) do (
if "%%s"=="VER_LAMEXP_MAJOR" set "VER_LAMEXP_MAJOR=%%~t" if "%%s"=="VER_LAMEXP_MAJOR" set "VER_LAMEXP_MAJOR=%%~t"
@ -25,6 +26,9 @@ if "%VER_LAMEXP_BUILD%"=="" GOTO:EOF
if "%VER_LAMEXP_TYPE%"=="" GOTO:EOF if "%VER_LAMEXP_TYPE%"=="" GOTO:EOF
if "%VER_LAMEXP_PATCH%"=="" GOTO:EOF if "%VER_LAMEXP_PATCH%"=="" GOTO:EOF
REM ------------------------------------------ REM ------------------------------------------
set "VER_LAMEXP_BASENAME=LameXP"
if not "%VER_LAMEXP_TYPE%" == "Final" set "VER_LAMEXP_BASENAME=LameXP-PRERELEASE"
REM ------------------------------------------
echo LameXP Version: echo LameXP Version:
echo %VER_LAMEXP_MAJOR%.%VER_LAMEXP_MINOR_HI%%VER_LAMEXP_MINOR_LO%, Build #%VER_LAMEXP_BUILD% (%VER_LAMEXP_TYPE%-%VER_LAMEXP_PATCH%) echo %VER_LAMEXP_MAJOR%.%VER_LAMEXP_MINOR_HI%%VER_LAMEXP_MINOR_LO%, Build #%VER_LAMEXP_BUILD% (%VER_LAMEXP_TYPE%-%VER_LAMEXP_PATCH%)
echo. echo.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -29,8 +29,8 @@
#define VER_LAMEXP_MINOR_HI 0 #define VER_LAMEXP_MINOR_HI 0
#define VER_LAMEXP_MINOR_LO 5 #define VER_LAMEXP_MINOR_LO 5
#define VER_LAMEXP_TYPE Alpha #define VER_LAMEXP_TYPE Alpha
#define VER_LAMEXP_PATCH 2 #define VER_LAMEXP_PATCH 3
#define VER_LAMEXP_BUILD 1027 #define VER_LAMEXP_BUILD 1031
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Tool versions (minimum expected versions!) // Tool versions (minimum expected versions!)

View File

@ -516,27 +516,27 @@ void MainWindow::addFiles(const QStringList &files)
tabWidget->setCurrentIndex(0); tabWidget->setCurrentIndex(0);
int timeMT = 0, timeST = 0; //int timeMT = 0, timeST = 0;
//
//--Prepass-- //--Prepass--
//
FileAnalyzer_ST *analyzerPre = new FileAnalyzer_ST(files); //FileAnalyzer_ST *analyzerPre = new FileAnalyzer_ST(files);
connect(analyzerPre, SIGNAL(fileSelected(QString)), m_banner, SLOT(setText(QString)), Qt::QueuedConnection); //connect(analyzerPre, SIGNAL(fileSelected(QString)), m_banner, SLOT(setText(QString)), Qt::QueuedConnection);
connect(analyzerPre, SIGNAL(progressValChanged(unsigned int)), m_banner, SLOT(setProgressVal(unsigned int)), Qt::QueuedConnection); //connect(analyzerPre, SIGNAL(progressValChanged(unsigned int)), m_banner, SLOT(setProgressVal(unsigned int)), Qt::QueuedConnection);
connect(analyzerPre, SIGNAL(progressMaxChanged(unsigned int)), m_banner, SLOT(setProgressMax(unsigned int)), Qt::QueuedConnection); //connect(analyzerPre, SIGNAL(progressMaxChanged(unsigned int)), m_banner, SLOT(setProgressMax(unsigned int)), Qt::QueuedConnection);
connect(analyzerPre, SIGNAL(fileAnalyzed(AudioFileModel)), m_fileListModel, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection); //connect(analyzerPre, SIGNAL(fileAnalyzed(AudioFileModel)), m_fileListModel, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection);
connect(m_banner, SIGNAL(userAbort()), analyzerPre, SLOT(abortProcess()), Qt::DirectConnection); //connect(m_banner, SIGNAL(userAbort()), analyzerPre, SLOT(abortProcess()), Qt::DirectConnection);
//
try //try
{ //{
m_fileListModel->setBlockUpdates(true); // m_fileListModel->setBlockUpdates(true);
m_banner->show(tr("Adding file(s), please wait..."), analyzerPre); // m_banner->show(tr("Adding file(s), please wait..."), analyzerPre);
} //}
catch(...) //catch(...)
{ //{
/* ignore any exceptions that may occur */ // /* ignore any exceptions that may occur */
} //}
//
//--MT-- //--MT--
FileAnalyzer *analyzer = new FileAnalyzer(files); FileAnalyzer *analyzer = new FileAnalyzer(files);
@ -551,7 +551,7 @@ void MainWindow::addFiles(const QStringList &files)
m_fileListModel->setBlockUpdates(true); m_fileListModel->setBlockUpdates(true);
QTime startTime = QTime::currentTime(); QTime startTime = QTime::currentTime();
m_banner->show(tr("Adding file(s), please wait..."), analyzer); m_banner->show(tr("Adding file(s), please wait..."), analyzer);
timeMT = startTime.secsTo(QTime::currentTime()); //timeMT = startTime.secsTo(QTime::currentTime());
} }
catch(...) catch(...)
{ {
@ -559,39 +559,39 @@ void MainWindow::addFiles(const QStringList &files)
} }
//--ST-- //--ST--
//
FileAnalyzer_ST *analyzerST = new FileAnalyzer_ST(files); //FileAnalyzer_ST *analyzerST = new FileAnalyzer_ST(files);
connect(analyzerST, SIGNAL(fileSelected(QString)), m_banner, SLOT(setText(QString)), Qt::QueuedConnection); //connect(analyzerST, SIGNAL(fileSelected(QString)), m_banner, SLOT(setText(QString)), Qt::QueuedConnection);
connect(analyzerST, SIGNAL(progressValChanged(unsigned int)), m_banner, SLOT(setProgressVal(unsigned int)), Qt::QueuedConnection); //connect(analyzerST, SIGNAL(progressValChanged(unsigned int)), m_banner, SLOT(setProgressVal(unsigned int)), Qt::QueuedConnection);
connect(analyzerST, SIGNAL(progressMaxChanged(unsigned int)), m_banner, SLOT(setProgressMax(unsigned int)), Qt::QueuedConnection); //connect(analyzerST, SIGNAL(progressMaxChanged(unsigned int)), m_banner, SLOT(setProgressMax(unsigned int)), Qt::QueuedConnection);
connect(analyzerST, SIGNAL(fileAnalyzed(AudioFileModel)), m_fileListModel, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection); //connect(analyzerST, SIGNAL(fileAnalyzed(AudioFileModel)), m_fileListModel, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection);
connect(m_banner, SIGNAL(userAbort()), analyzerST, SLOT(abortProcess()), Qt::DirectConnection); //connect(m_banner, SIGNAL(userAbort()), analyzerST, SLOT(abortProcess()), Qt::DirectConnection);
//
try //try
{ //{
m_fileListModel->setBlockUpdates(true); // m_fileListModel->setBlockUpdates(true);
QTime startTime = QTime::currentTime(); // QTime startTime = QTime::currentTime();
m_banner->show(tr("Adding file(s), please wait..."), analyzerST); // m_banner->show(tr("Adding file(s), please wait..."), analyzerST);
timeST = startTime.secsTo(QTime::currentTime()); // timeST = startTime.secsTo(QTime::currentTime());
} //}
catch(...) //catch(...)
{ //{
/* ignore any exceptions that may occur */ // /* ignore any exceptions that may occur */
} //}
//
//------ //------
//
if(timeST > 0 && timeMT > 0) //if(timeST > 0 && timeMT > 0)
{ //{
double speedUp = static_cast<double>(timeST) / static_cast<double>(timeMT); // double speedUp = static_cast<double>(timeST) / static_cast<double>(timeMT);
qWarning("ST: %d, MT: %d", timeST, timeMT); // qWarning("ST: %d, MT: %d", timeST, timeMT);
QMessageBox::information(this, "Speed Up", QString().sprintf("Announcement: The new multi-threaded file analyzer is %.1fx faster !!!", speedUp), QMessageBox::Ok); // QMessageBox::information(this, "Speed Up", QString().sprintf("Announcement: The new multi-threaded file analyzer is %.1fx faster !!!", speedUp), QMessageBox::Ok);
} //}
else //else
{ //{
QMessageBox::information(this, "Speed Up", "Couldn't compare the the new multi-threaded file analyzer this time!", QMessageBox::Ok); // QMessageBox::information(this, "Speed Up", "Couldn't compare the the new multi-threaded file analyzer this time!", QMessageBox::Ok);
} //}
//
//------ //------
m_fileListModel->setBlockUpdates(false); m_fileListModel->setBlockUpdates(false);
@ -619,8 +619,8 @@ void MainWindow::addFiles(const QStringList &files)
} }
LAMEXP_DELETE(analyzer); LAMEXP_DELETE(analyzer);
LAMEXP_DELETE(analyzerST); //LAMEXP_DELETE(analyzerST);
LAMEXP_DELETE(analyzerPre); //LAMEXP_DELETE(analyzerPre);
m_banner->close(); m_banner->close();
} }

View File

@ -108,6 +108,8 @@ const char *FileAnalyzer::g_tags_aud[] =
void FileAnalyzer::run() void FileAnalyzer::run()
{ {
qWarning("--- FileAnalyzer::run() ---");
m_abortFlag = false; m_abortFlag = false;
m_bAborted = false; m_bAborted = false;
@ -139,40 +141,34 @@ void FileAnalyzer::run()
{ {
while(!(m_inputFiles.isEmpty() || m_bAborted)) while(!(m_inputFiles.isEmpty() || m_bAborted))
{ {
const QString currentFile = QDir::fromNativeSeparators(m_inputFiles.takeFirst()); if(!AnalyzeTask::waitForFreeSlot(&m_abortFlag))
AnalyzeTask *task = new AnalyzeTask(currentFile, m_templateFile->filePath(), &m_abortFlag);
connect(task, SIGNAL(fileSelected(QString)), this, SIGNAL(fileSelected(QString)), Qt::DirectConnection);
connect(task, SIGNAL(progressValChanged(unsigned int)), this, SIGNAL(progressValChanged(unsigned int)), Qt::DirectConnection);
connect(task, SIGNAL(progressMaxChanged(unsigned int)), this, SIGNAL(progressMaxChanged(unsigned int)), Qt::DirectConnection);
connect(task, SIGNAL(fileAnalyzed(AudioFileModel)), this, SIGNAL(fileAnalyzed(AudioFileModel)), Qt::DirectConnection);
while(!pool->tryStart(task))
{ {
AnalyzeTask::waitForOneThread(); qWarning("Timeout in AnalyzeTask::waitForFreeSlot() !!!");
if(m_abortFlag)
{
LAMEXP_DELETE(task);
break;
}
QThread::yieldCurrentThread();
} }
if(m_abortFlag) if(m_abortFlag)
{ {
MessageBeep(MB_ICONERROR); MessageBeep(MB_ICONERROR);
m_bAborted = true; m_bAborted = true;
break;
} }
if(!m_bAborted) if(!m_bAborted)
{ {
const QString currentFile = QDir::fromNativeSeparators(m_inputFiles.takeFirst());
AnalyzeTask *task = new AnalyzeTask(currentFile, m_templateFile->filePath(), &m_abortFlag);
connect(task, SIGNAL(fileSelected(QString)), this, SIGNAL(fileSelected(QString)), Qt::DirectConnection);
connect(task, SIGNAL(progressValChanged(unsigned int)), this, SIGNAL(progressValChanged(unsigned int)), Qt::DirectConnection);
connect(task, SIGNAL(progressMaxChanged(unsigned int)), this, SIGNAL(progressMaxChanged(unsigned int)), Qt::DirectConnection);
connect(task, SIGNAL(fileAnalyzed(AudioFileModel)), this, SIGNAL(fileAnalyzed(AudioFileModel)), Qt::DirectConnection);
pool->start(task);
if(int count = AnalyzeTask::getAdditionalFiles(m_inputFiles)) if(int count = AnalyzeTask::getAdditionalFiles(m_inputFiles))
{ {
emit progressMaxChanged(nFiles += count); emit progressMaxChanged(nFiles += count);
} }
QThread::msleep(8);
} }
} }

View File

@ -50,6 +50,7 @@ QMutex AnalyzeTask::s_waitMutex;
QWaitCondition AnalyzeTask::s_waitCond; QWaitCondition AnalyzeTask::s_waitCond;
QSet<unsigned int> AnalyzeTask::s_threadIdx_running; QSet<unsigned int> AnalyzeTask::s_threadIdx_running;
unsigned int AnalyzeTask::s_threadIdx_next = 0; unsigned int AnalyzeTask::s_threadIdx_next = 0;
QSemaphore AnalyzeTask::s_semaphore(0);
/* more static vars */ /* more static vars */
QReadWriteLock AnalyzeTask::s_lock; QReadWriteLock AnalyzeTask::s_lock;
@ -64,6 +65,7 @@ QSet<QString> AnalyzeTask::s_recentlyAdded;
/*constants*/ /*constants*/
const int WAITCOND_TIMEOUT = 2500; const int WAITCOND_TIMEOUT = 2500;
const int MAX_RETRIES = 60000 / WAITCOND_TIMEOUT; const int MAX_RETRIES = 60000 / WAITCOND_TIMEOUT;
const int MAX_QUEUE_SLOTS = 32;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Constructor // Constructor
@ -86,6 +88,8 @@ AnalyzeTask::AnalyzeTask(const QString &inputFile, const QString &templateFile,
AnalyzeTask::~AnalyzeTask(void) AnalyzeTask::~AnalyzeTask(void)
{ {
s_semaphore.release();
s_waitMutex.lock(); s_waitMutex.lock();
s_threadIdx_running.remove(m_threadIdx); s_threadIdx_running.remove(m_threadIdx);
s_waitMutex.unlock(); s_waitMutex.unlock();
@ -817,13 +821,15 @@ int AnalyzeTask::getAdditionalFiles(QStringList &fileList)
return 0; return 0;
} }
bool AnalyzeTask::waitForOneThread(void) bool AnalyzeTask::waitForFreeSlot(volatile bool *abortFlag)
{ {
bool ret = false; bool ret = false;
s_waitMutex.lock(); for(int i = 0; i < MAX_RETRIES; i++)
ret = s_waitCond.wait(&s_waitMutex, WAITCOND_TIMEOUT); {
s_waitMutex.unlock(); ret = s_semaphore.tryAcquire(1, WAITCOND_TIMEOUT);
if(ret || (*abortFlag)) break;
}
return ret; return ret;
} }
@ -844,6 +850,12 @@ void AnalyzeTask::reset(void)
s_threadIdx_next = 0; s_threadIdx_next = 0;
s_threadIdx_running.clear(); s_threadIdx_running.clear();
s_waitMutex.unlock(); s_waitMutex.unlock();
int freeSlots = s_semaphore.available();
if(freeSlots < MAX_QUEUE_SLOTS)
{
s_semaphore.release(MAX_QUEUE_SLOTS - freeSlots);
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -26,6 +26,7 @@
#include <QWaitCondition> #include <QWaitCondition>
#include <QStringList> #include <QStringList>
#include <QMutex> #include <QMutex>
#include <QSemaphore>
class AudioFileModel; class AudioFileModel;
class QFile; class QFile;
@ -53,8 +54,8 @@ public:
static unsigned int filesDummyCDDA(void); static unsigned int filesDummyCDDA(void);
static unsigned int filesCueSheet(void); static unsigned int filesCueSheet(void);
//Wait till the next running thread terminates //Wait until there is a free slot in the queue
static bool waitForOneThread(void); static bool waitForFreeSlot(volatile bool *abortFlag);
signals: signals:
void fileSelected(const QString &fileName); void fileSelected(const QString &fileName);
@ -105,6 +106,8 @@ private:
static QSet<unsigned int> s_threadIdx_running; static QSet<unsigned int> s_threadIdx_running;
static unsigned int s_threadIdx_next; static unsigned int s_threadIdx_next;
static QSemaphore s_semaphore;
static QReadWriteLock s_lock; static QReadWriteLock s_lock;
static unsigned int s_filesAccepted; static unsigned int s_filesAccepted;
static unsigned int s_filesRejected; static unsigned int s_filesRejected;