Browse Source

Projucer: Use std::async instead of ThreadPool in module scanner

v6.1.6
reuk 3 years ago
parent
commit
5a621e811f
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
1 changed files with 58 additions and 94 deletions
  1. +58
    -94
      extras/Projucer/Source/Project/Modules/jucer_AvailableModulesList.h

+ 58
- 94
extras/Projucer/Source/Project/Modules/jucer_AvailableModulesList.h View File

@@ -27,6 +27,8 @@
#include "jucer_ModuleDescription.h"
#include <future>
//==============================================================================
class AvailableModulesList : private AsyncUpdater
{
@@ -39,16 +41,36 @@ public:
//==============================================================================
void scanPaths (const Array<File>& paths)
{
auto job = createScannerJob (paths);
auto& ref = *job;
removePendingAndAddJob (std::move (job));
scanPool.waitForJobToFinish (&ref, -1);
scanPathsAsync (paths);
scanner = {};
}
void scanPathsAsync (const Array<File>& 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<File>& paths,
std::function<void (const ModuleIDAndFolderList&)>&& 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<FileAndDepth> 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<FileAndDepth> 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<File> pathsToScan;
std::function<void (const ModuleIDAndFolderList&)> completionCallback;
};
}
//==============================================================================
void handleAsyncUpdate() override
@@ -181,31 +168,8 @@ private:
listeners.call ([this] (Listener& l) { l.availableModulesChanged (this); });
}
std::unique_ptr<ThreadPoolJob> createScannerJob (const Array<File>& paths)
{
return std::make_unique<ModuleScannerJob> (paths, [this] (ModuleIDAndFolderList scannedModulesList)
{
if (scannedModulesList == modulesList)
return;
{
const ScopedLock swapLock (lock);
modulesList.swap (scannedModulesList);
}
triggerAsyncUpdate();
});
}
void removePendingAndAddJob (std::unique_ptr<ThreadPoolJob> jobToAdd)
{
scanPool.removeAllJobs (false, 100);
scanPool.addJob (jobToAdd.release(), true);
}
//==============================================================================
ThreadPool scanPool { 1 };
std::future<void> scanner;
ModuleIDAndFolderList modulesList;
ListenerList<Listener> listeners;
CriticalSection lock;


Loading…
Cancel
Save