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:
parent
61dc8e34c4
commit
a291771153
@ -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 ::
|
||||
|
@ -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
@ -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!)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user