diff --git a/src/localLister.cpp b/src/localLister.cpp index fcc5b893fa6ec42a824739060e129aadac9b8942..de41ad3006dd1db4ad46f944f01af3e2b14df66e 100644 --- a/src/localLister.cpp +++ b/src/localLister.cpp @@ -16,6 +16,8 @@ #include #include //postEvent() #include +#include +#include #include #include @@ -140,6 +142,8 @@ LocalLister::scan(const QByteArray &path, const QByteArray &dirname) #define KDE_lstat kdewin32_stat64 #endif + QVector> subDirectories; + struct stat statbuf; dirent *ent; while ((ent = readdir(dir))) @@ -150,8 +154,9 @@ LocalLister::scan(const QByteArray &path, const QByteArray &dirname) return cwd; } - if (qstrcmp(ent->d_name, ".") == 0 || qstrcmp(ent->d_name, "..") == 0) + if (qstrcmp(ent->d_name, ".") == 0 || qstrcmp(ent->d_name, "..") == 0) { continue; + } // QStringBuilder is used here. It assumes ent->d_name is char[NAME_MAX + 1], // and thus copies only first NAME_MAX + 1 chars. @@ -191,6 +196,7 @@ LocalLister::scan(const QByteArray &path, const QByteArray &dirname) //check to see if we've scanned this section already + QMutexLocker lock(&m_treeMutex); for (Folder *folder : *m_trees) { if (new_path == folder->name8Bit()) @@ -202,10 +208,11 @@ LocalLister::scan(const QByteArray &path, const QByteArray &dirname) cwd->append(folder, new_dirname.constData()); } } + lock.unlock(); - if (!d) //then scan - if ((d = scan(new_path, new_dirname))) //then scan was successful - cwd->append(d); + if (!d) { //then scan + subDirectories.append({new_path, new_dirname}); + } } ++m_parent->m_files; @@ -213,6 +220,27 @@ LocalLister::scan(const QByteArray &path, const QByteArray &dirname) closedir(dir); + // Scan all subdirectories, either in separate threads or immediately, + // depending on how many free threads there are in the threadpool. + // Yes, it isn't optimal, but it's better than nothing and pretty simple. + QVector returnedCwds(subDirectories.count()); + QSemaphore semaphore; + for (int i=0; i scanSubdir = [this, i, &subDirectories, &semaphore, &returnedCwds]() { + returnedCwds[i] = scan(subDirectories[i].first, subDirectories[i].second); + semaphore.release(1); + }; + if (!QThreadPool::globalInstance()->tryStart(scanSubdir)) { + scanSubdir(); + } + } + semaphore.acquire(subDirectories.count()); + for (Folder *d : std::as_const(returnedCwds)) { + if (d) { //then scan was successful + cwd->append(d); + } + } + std::sort(cwd->files.begin(), cwd->files.end(), [](File *a, File*b) { return a->size() > b->size(); }); return cwd; diff --git a/src/localLister.h b/src/localLister.h index 3db976b1ca9daacdb2c4df68de041d672340b2b6..f97906b61ae6534886fdf65c6fc1363826f771f9 100644 --- a/src/localLister.h +++ b/src/localLister.h @@ -10,6 +10,7 @@ #include #include +#include class Folder; @@ -31,6 +32,7 @@ Q_SIGNALS: private: QString m_path; + QMutex m_treeMutex; QList *m_trees; ScanManager *m_parent; diff --git a/src/scan.h b/src/scan.h index a4fd892103aa25ecd544c4604c3f78395a93c54b..899b77d78b7638de3aba1f54e9f5891a58fb2ff0 100644 --- a/src/scan.h +++ b/src/scan.h @@ -12,6 +12,8 @@ #include #include +#include + class Folder; namespace Filelight @@ -54,7 +56,7 @@ Q_SIGNALS: void branchCacheHit(Folder* tree); private: - bool m_abort; + std::atomic_bool m_abort; QAtomicInt m_files; QAtomicInteger m_totalSize;