diff --git a/doc/Changelog.html b/doc/Changelog.html
index d820e5a2..765bede9 100644
--- a/doc/Changelog.html
+++ b/doc/Changelog.html
@@ -20,6 +20,7 @@ a:visited { color: #0000EE; }
Added Swedish translation, thanks to Åke Engelbrektson <eson57@gmail.com>
Implemented multi-threading in initialization code for faster application startup
Implemented multi-threading in file analyzer for faster file import
+Fixed a potential crash (stack overflow) when adding a huge number of files
Changes between v4.03 and v4.04 [2012-04-26]:
diff --git a/src/Config.h b/src/Config.h
index 93d089aa..cd58fae9 100644
--- a/src/Config.h
+++ b/src/Config.h
@@ -30,7 +30,7 @@
#define VER_LAMEXP_MINOR_LO 5
#define VER_LAMEXP_TYPE Alpha
#define VER_LAMEXP_PATCH 1
-#define VER_LAMEXP_BUILD 1005
+#define VER_LAMEXP_BUILD 1008
///////////////////////////////////////////////////////////////////////////////
// Tool versions (minimum expected versions!)
diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp
index 122aa074..2b0c9ec4 100644
--- a/src/Dialog_MainWindow.cpp
+++ b/src/Dialog_MainWindow.cpp
@@ -519,7 +519,22 @@ void MainWindow::addFiles(const QStringList &files)
connect(analyzer, SIGNAL(fileAnalyzed(AudioFileModel)), m_fileListModel, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection);
connect(m_banner, SIGNAL(userAbort()), analyzer, SLOT(abortProcess()), Qt::DirectConnection);
- m_banner->show(tr("Adding file(s), please wait..."), analyzer);
+ try
+ {
+ m_fileListModel->setBlockUpdates(true);
+ m_banner->show(tr("Adding file(s), please wait..."), analyzer);
+ }
+ catch(...)
+ {
+ /* ignore any exceptions that may occur */
+ }
+
+ m_fileListModel->setBlockUpdates(false);
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
+ sourceFileView->update();
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
+ sourceFileView->scrollToBottom();
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
if(analyzer->filesDenied())
{
@@ -539,7 +554,6 @@ void MainWindow::addFiles(const QStringList &files)
}
LAMEXP_DELETE(analyzer);
- sourceFileView->scrollToBottom();
m_banner->close();
}
diff --git a/src/Dialog_WorkingBanner.cpp b/src/Dialog_WorkingBanner.cpp
index cd5d7e89..95844696 100644
--- a/src/Dialog_WorkingBanner.cpp
+++ b/src/Dialog_WorkingBanner.cpp
@@ -50,7 +50,7 @@ WorkingBanner::WorkingBanner(QWidget *parent)
//Start animation
m_working = new QMovie(":/images/Busy.gif");
- m_working->setSpeed(25);
+ m_working->setSpeed(50);
labelWorking->setMovie(m_working);
m_working->start();
diff --git a/src/Model_FileList.cpp b/src/Model_FileList.cpp
index eee4733e..f733fbd4 100644
--- a/src/Model_FileList.cpp
+++ b/src/Model_FileList.cpp
@@ -40,6 +40,7 @@
FileListModel::FileListModel(void)
:
+ m_blockUpdates(false),
m_fileIcon(":/icons/page_white_cd.png")
{
}
@@ -138,26 +139,28 @@ void FileListModel::addFile(const QString &filePath)
{
QFileInfo fileInfo(filePath);
const QString key = MAKE_KEY(fileInfo.canonicalFilePath());
+ const bool flag = (!m_blockUpdates);
if(!m_fileStore.contains(key))
{
- beginInsertRows(QModelIndex(), m_fileList.count(), m_fileList.count());
+ if(flag) beginInsertRows(QModelIndex(), m_fileList.count(), m_fileList.count());
m_fileStore.insert(key, AudioFileModel(fileInfo.canonicalFilePath(), fileInfo.baseName()));
m_fileList.append(key);
- endInsertRows();
+ if(flag) endInsertRows();
}
}
void FileListModel::addFile(const AudioFileModel &file)
{
const QString key = MAKE_KEY(file.filePath());
+ const bool flag = (!m_blockUpdates);
if(!m_fileStore.contains(key))
{
- beginInsertRows(QModelIndex(), m_fileList.count(), m_fileList.count());
+ if(flag) beginInsertRows(QModelIndex(), m_fileList.count(), m_fileList.count());
m_fileStore.insert(key, file);
m_fileList.append(key);
- endInsertRows();
+ if(flag) endInsertRows();
}
}
diff --git a/src/Model_FileList.h b/src/Model_FileList.h
index 2b09e2d6..5384c3e1 100644
--- a/src/Model_FileList.h
+++ b/src/Model_FileList.h
@@ -65,11 +65,19 @@ public:
}
CsvError;
+ //Speed hacks
+ void setBlockUpdates(bool flag)
+ {
+ m_blockUpdates = flag;
+ if(!flag) reset();
+ }
+
public slots:
void addFile(const QString &filePath);
void addFile(const AudioFileModel &file);
private:
+ bool m_blockUpdates;
QList m_fileList;
QHash m_fileStore;
const QIcon m_fileIcon;
diff --git a/src/Thread_FileAnalyzer.cpp b/src/Thread_FileAnalyzer.cpp
index 545c0d51..2b0c1719 100644
--- a/src/Thread_FileAnalyzer.cpp
+++ b/src/Thread_FileAnalyzer.cpp
@@ -143,13 +143,18 @@ void FileAnalyzer::run()
while(!pool->tryStart(task))
{
- AnalyzeTask::waitForOneThread(1250);
+ if(!AnalyzeTask::waitForOneThread(1250))
+ {
+ qWarning("FileAnalyzer::run() -> Timeout !!!");
+ }
if(m_abortFlag)
{
LAMEXP_DELETE(task);
break;
}
+
+ QThread::yieldCurrentThread();
}
if(m_abortFlag)
diff --git a/src/Thread_FileAnalyzer_Task.cpp b/src/Thread_FileAnalyzer_Task.cpp
index 0b70971b..fa5b46af 100644
--- a/src/Thread_FileAnalyzer_Task.cpp
+++ b/src/Thread_FileAnalyzer_Task.cpp
@@ -80,7 +80,7 @@ AnalyzeTask::AnalyzeTask(const QString &inputFile, const QString &templateFile,
AnalyzeTask::~AnalyzeTask(void)
{
QWriteLocker lock(&s_lock);
- s_threadIdx_finished = qMax(s_threadIdx_finished, m_threadIdx + 1);
+ s_threadIdx_finished = qMax(s_threadIdx_finished, m_threadIdx + 1ui64);
s_waitCond.wakeAll();
}
@@ -88,7 +88,23 @@ AnalyzeTask::~AnalyzeTask(void)
// Thread Main
////////////////////////////////////////////////////////////
-void AnalyzeTask::run(void)
+void AnalyzeTask::run()
+{
+ try
+ {
+ run_ex();
+ }
+ catch(...)
+ {
+ qWarning("WARNING: Caught an in exception AnalyzeTask thread!");
+ }
+
+ QWriteLocker lock(&s_lock);
+ s_threadIdx_finished = qMax(s_threadIdx_finished, m_threadIdx + 1ui64);
+ s_waitCond.wakeAll();
+}
+
+void AnalyzeTask::run_ex(void)
{
int fileType = fileTypeNormal;
QString currentFile = QDir::fromNativeSeparators(m_inputFile);
@@ -707,7 +723,10 @@ void AnalyzeTask::waitForPreviousThreads(void)
}
lock.unlock();
- waitForOneThread(1250);
+ if(!AnalyzeTask::waitForOneThread(1250))
+ {
+ qWarning("AnalyzeTask::waitForPreviousThreads -> Timeout !!!");
+ }
}
}
diff --git a/src/Thread_FileAnalyzer_Task.h b/src/Thread_FileAnalyzer_Task.h
index 6f541009..2cbb4ae3 100644
--- a/src/Thread_FileAnalyzer_Task.h
+++ b/src/Thread_FileAnalyzer_Task.h
@@ -54,20 +54,22 @@ public:
static unsigned int filesCueSheet(void);
//Wait till the next running thread terminates
- static void waitForOneThread(unsigned long timeout)
+ static __forceinline bool waitForOneThread(unsigned long timeout)
{
+ bool ret = false;
s_waitMutex.lock();
- s_waitCond.wait(&s_waitMutex, timeout);
+ ret = s_waitCond.wait(&s_waitMutex, timeout);
s_waitMutex.unlock();
+ return ret;
}
- void run(void);
-
signals:
void fileSelected(const QString &fileName);
void fileAnalyzed(const AudioFileModel &file);
protected:
+ void run(void);
+ void run_ex(void);
private:
enum cover_t