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
)
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 (
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!.zip" 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%\..\%VER_LAMEXP_BASENAME%.%ISO_DATE%.%LAMEXP_CONFIG:_=-%.Build-%VER_LAMEXP_BUILD%.Update-%%n"
)
REM ------------------------------------------
REM :: DELETE OLD OUTPUT FILE ::

View File

@ -7,6 +7,7 @@ set "VER_LAMEXP_MINOR_LO="
set "VER_LAMEXP_BUILD="
set "VER_LAMEXP_TYPE="
set "VER_LAMEXP_PATCH="
set "VER_LAMEXP_BASENAME="
REM ------------------------------------------
for /f "tokens=2,*" %%s in (%~dp0\..\..\src\Config.h) do (
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_PATCH%"=="" GOTO:EOF
REM ------------------------------------------
set "VER_LAMEXP_BASENAME=LameXP"
if not "%VER_LAMEXP_TYPE%" == "Final" set "VER_LAMEXP_BASENAME=LameXP-PRERELEASE"
REM ------------------------------------------
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.

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_LO 5
#define VER_LAMEXP_TYPE Alpha
#define VER_LAMEXP_PATCH 2
#define VER_LAMEXP_BUILD 1027
#define VER_LAMEXP_PATCH 3
#define VER_LAMEXP_BUILD 1031
///////////////////////////////////////////////////////////////////////////////
// Tool versions (minimum expected versions!)

View File

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

View File

@ -108,6 +108,8 @@ const char *FileAnalyzer::g_tags_aud[] =
void FileAnalyzer::run()
{
qWarning("--- FileAnalyzer::run() ---");
m_abortFlag = false;
m_bAborted = false;
@ -139,40 +141,34 @@ void FileAnalyzer::run()
{
while(!(m_inputFiles.isEmpty() || 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);
while(!pool->tryStart(task))
if(!AnalyzeTask::waitForFreeSlot(&m_abortFlag))
{
AnalyzeTask::waitForOneThread();
if(m_abortFlag)
{
LAMEXP_DELETE(task);
break;
}
QThread::yieldCurrentThread();
qWarning("Timeout in AnalyzeTask::waitForFreeSlot() !!!");
}
if(m_abortFlag)
{
MessageBeep(MB_ICONERROR);
m_bAborted = true;
break;
}
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))
{
emit progressMaxChanged(nFiles += count);
}
QThread::msleep(8);
}
}

View File

@ -50,6 +50,7 @@ QMutex AnalyzeTask::s_waitMutex;
QWaitCondition AnalyzeTask::s_waitCond;
QSet<unsigned int> AnalyzeTask::s_threadIdx_running;
unsigned int AnalyzeTask::s_threadIdx_next = 0;
QSemaphore AnalyzeTask::s_semaphore(0);
/* more static vars */
QReadWriteLock AnalyzeTask::s_lock;
@ -64,6 +65,7 @@ QSet<QString> AnalyzeTask::s_recentlyAdded;
/*constants*/
const int WAITCOND_TIMEOUT = 2500;
const int MAX_RETRIES = 60000 / WAITCOND_TIMEOUT;
const int MAX_QUEUE_SLOTS = 32;
////////////////////////////////////////////////////////////
// Constructor
@ -86,6 +88,8 @@ AnalyzeTask::AnalyzeTask(const QString &inputFile, const QString &templateFile,
AnalyzeTask::~AnalyzeTask(void)
{
s_semaphore.release();
s_waitMutex.lock();
s_threadIdx_running.remove(m_threadIdx);
s_waitMutex.unlock();
@ -817,13 +821,15 @@ int AnalyzeTask::getAdditionalFiles(QStringList &fileList)
return 0;
}
bool AnalyzeTask::waitForOneThread(void)
bool AnalyzeTask::waitForFreeSlot(volatile bool *abortFlag)
{
bool ret = false;
s_waitMutex.lock();
ret = s_waitCond.wait(&s_waitMutex, WAITCOND_TIMEOUT);
s_waitMutex.unlock();
for(int i = 0; i < MAX_RETRIES; i++)
{
ret = s_semaphore.tryAcquire(1, WAITCOND_TIMEOUT);
if(ret || (*abortFlag)) break;
}
return ret;
}
@ -844,6 +850,12 @@ void AnalyzeTask::reset(void)
s_threadIdx_next = 0;
s_threadIdx_running.clear();
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 <QStringList>
#include <QMutex>
#include <QSemaphore>
class AudioFileModel;
class QFile;
@ -53,8 +54,8 @@ public:
static unsigned int filesDummyCDDA(void);
static unsigned int filesCueSheet(void);
//Wait till the next running thread terminates
static bool waitForOneThread(void);
//Wait until there is a free slot in the queue
static bool waitForFreeSlot(volatile bool *abortFlag);
signals:
void fileSelected(const QString &fileName);
@ -105,6 +106,8 @@ private:
static QSet<unsigned int> s_threadIdx_running;
static unsigned int s_threadIdx_next;
static QSemaphore s_semaphore;
static QReadWriteLock s_lock;
static unsigned int s_filesAccepted;
static unsigned int s_filesRejected;