From 5a621e811f8afd7734816392b2d1faaae4a73d1e Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 18 Nov 2021 21:37:47 +0000 Subject: [PATCH] Projucer: Use std::async instead of ThreadPool in module scanner --- .../Modules/jucer_AvailableModulesList.h | 152 +++++++----------- 1 file changed, 58 insertions(+), 94 deletions(-) diff --git a/extras/Projucer/Source/Project/Modules/jucer_AvailableModulesList.h b/extras/Projucer/Source/Project/Modules/jucer_AvailableModulesList.h index e1494dd014..35355c0f72 100644 --- a/extras/Projucer/Source/Project/Modules/jucer_AvailableModulesList.h +++ b/extras/Projucer/Source/Project/Modules/jucer_AvailableModulesList.h @@ -27,6 +27,8 @@ #include "jucer_ModuleDescription.h" +#include + //============================================================================== class AvailableModulesList : private AsyncUpdater { @@ -39,16 +41,36 @@ public: //============================================================================== void scanPaths (const Array& paths) { - auto job = createScannerJob (paths); - auto& ref = *job; - - removePendingAndAddJob (std::move (job)); - scanPool.waitForJobToFinish (&ref, -1); + scanPathsAsync (paths); + scanner = {}; } void scanPathsAsync (const Array& paths) { - removePendingAndAddJob (createScannerJob (paths)); + scanner = std::async (std::launch::async, [this, paths] + { + ModuleIDAndFolderList list; + + for (auto& p : paths) + addAllModulesInFolder (p, list); + + std::sort (list.begin(), list.end(), [] (const ModuleIDAndFolder& m1, + const ModuleIDAndFolder& m2) + { + return m1.first.compareIgnoreCase (m2.first) < 0; + }); + + { + const ScopedLock swapLock (lock); + + if (list == modulesList) + return; + + modulesList.swap (list); + } + + triggerAsyncUpdate(); + }); } //============================================================================== @@ -95,85 +117,50 @@ public: private: //============================================================================== - struct ModuleScannerJob : public ThreadPoolJob + static bool tryToAddModuleFromFolder (const File& path, ModuleIDAndFolderList& list) { - ModuleScannerJob (const Array& paths, - std::function&& callback) - : ThreadPoolJob ("ModuleScannerJob"), - pathsToScan (paths), - completionCallback (std::move (callback)) - { - } + ModuleDescription m (path); - JobStatus runJob() override + if (m.isValid() + && std::none_of (list.begin(), list.end(), + [&m] (const ModuleIDAndFolder& element) { return element.first == m.getID(); })) { - ModuleIDAndFolderList list; - - for (auto& p : pathsToScan) - addAllModulesInFolder (p, list); - - if (! shouldExit()) - { - std::sort (list.begin(), list.end(), [] (const ModuleIDAndFolder& m1, - const ModuleIDAndFolder& m2) - { - return m1.first.compareIgnoreCase (m2.first) < 0; - }); - - completionCallback (list); - } - - return jobHasFinished; + list.push_back ({ m.getID(), path }); + return true; } - static bool tryToAddModuleFromFolder (const File& path, ModuleIDAndFolderList& list) - { - ModuleDescription m (path); + return false; + } - if (m.isValid() - && std::none_of (list.begin(), list.end(), - [&m] (const ModuleIDAndFolder& element) { return element.first == m.getID(); })) - { - list.push_back ({ m.getID(), path }); - return true; - } + static void addAllModulesInFolder (const File& topLevelPath, ModuleIDAndFolderList& list) + { + struct FileAndDepth + { + File file; + int depth; + }; - return false; - } + std::queue pathsToCheck; + pathsToCheck.push ({ topLevelPath, 0 }); - static void addAllModulesInFolder (const File& topLevelPath, ModuleIDAndFolderList& list) + while (! pathsToCheck.empty()) { - struct FileAndDepth - { - File file; - int depth; - }; + const auto path = pathsToCheck.front(); + pathsToCheck.pop(); - std::queue pathsToCheck; - pathsToCheck.push ({ topLevelPath, 0 }); + if (tryToAddModuleFromFolder (path.file, list) || path.depth == 3) + continue; - while (! pathsToCheck.empty()) + for (const auto& iter : RangedDirectoryIterator (path.file, false, "*", File::findDirectories)) { - const auto path = pathsToCheck.front(); - pathsToCheck.pop(); - - if (tryToAddModuleFromFolder (path.file, list) || path.depth == 3) - continue; + if (auto* job = ThreadPoolJob::getCurrentThreadPoolJob()) + if (job->shouldExit()) + return; - for (const auto& iter : RangedDirectoryIterator (path.file, false, "*", File::findDirectories)) - { - if (auto* job = ThreadPoolJob::getCurrentThreadPoolJob()) - if (job->shouldExit()) - return; - - pathsToCheck.push({ iter.getFile(), path.depth + 1 }); - } + pathsToCheck.push({ iter.getFile(), path.depth + 1 }); } } - - Array pathsToScan; - std::function completionCallback; - }; + } //============================================================================== void handleAsyncUpdate() override @@ -181,31 +168,8 @@ private: listeners.call ([this] (Listener& l) { l.availableModulesChanged (this); }); } - std::unique_ptr createScannerJob (const Array& paths) - { - return std::make_unique (paths, [this] (ModuleIDAndFolderList scannedModulesList) - { - if (scannedModulesList == modulesList) - return; - - { - const ScopedLock swapLock (lock); - modulesList.swap (scannedModulesList); - } - - triggerAsyncUpdate(); - }); - } - - void removePendingAndAddJob (std::unique_ptr jobToAdd) - { - scanPool.removeAllJobs (false, 100); - scanPool.addJob (jobToAdd.release(), true); - } - //============================================================================== - ThreadPool scanPool { 1 }; - + std::future scanner; ModuleIDAndFolderList modulesList; ListenerList listeners; CriticalSection lock;