summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modinfo.cpp11
-rw-r--r--src/modinfo.h31
-rw-r--r--src/thread_utils.h55
3 files changed, 57 insertions, 40 deletions
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index 81b45a49..eb0f0b4f 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -29,7 +29,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "modinfodialog.h"
#include "overwriteinfodialog.h"
#include "versioninfo.h"
-#include "envfs.h"
+#include "thread_utils.h"
#include <iplugingame.h>
#include <versioninfo.h>
@@ -46,7 +46,6 @@ using namespace MOBase;
using namespace MOShared;
-env::ThreadPool<ModInfo::ModThread> ModInfo::s_Threads;
std::vector<ModInfo::Ptr> ModInfo::s_Collection;
std::map<QString, unsigned int> ModInfo::s_ModsByName;
std::map<std::pair<QString, int>, std::vector<unsigned int>> ModInfo::s_ModsByModID;
@@ -289,13 +288,7 @@ void ModInfo::updateFromDisc(const QString &modDirectory,
std::sort(s_Collection.begin(), s_Collection.end(), ModInfo::ByName);
- // This force loading a part of the FileTree:
- s_Threads.setMax(refreshThreadCount);
- for (auto& p : s_Collection) {
- auto& t = s_Threads.request();
- t.ptr = p;
- t.wakeup();
- }
+ parallelMap(std::begin(s_Collection), std::end(s_Collection), &ModInfo::isValid, refreshThreadCount);
updateIndices();
diff --git a/src/modinfo.h b/src/modinfo.h
index 081f3660..37a2d24d 100644
--- a/src/modinfo.h
+++ b/src/modinfo.h
@@ -22,7 +22,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "imodinterface.h"
#include "versioninfo.h"
-#include "envfs.h"
class PluginContainer;
class QDir;
@@ -841,36 +840,6 @@ protected:
private:
- struct ModThread
- {
- ModInfo::Ptr ptr;
-
- std::condition_variable cv;
- std::mutex mutex;
- bool ready = false;
-
- void wakeup()
- {
- {
- std::scoped_lock lock(mutex);
- ready = true;
- }
-
- cv.notify_one();
- }
-
- void run()
- {
- std::unique_lock lock(mutex);
- cv.wait(lock, [&] { return ready; });
-
- ptr->isValid();
- ready = false;
- }
- };
-
- static env::ThreadPool<ModThread> s_Threads;
-
static QMutex s_Mutex;
static std::map<std::pair<QString, int>, std::vector<unsigned int> > s_ModsByModID;
static int s_NextID;
diff --git a/src/thread_utils.h b/src/thread_utils.h
new file mode 100644
index 00000000..fe096a36
--- /dev/null
+++ b/src/thread_utils.h
@@ -0,0 +1,55 @@
+#ifndef MO2_THREAD_UTILS_H
+#define MO2_THREAD_UTILS_H
+
+#include <mutex>
+#include <thread>
+
+namespace MOShared {
+
+/**
+ * @brief Apply the given callable to each element between the two given iterators
+ * in a parallel way.
+ *
+ * The callable should be independent, or properly synchronized, and the source of
+ * the range should not change during this call.
+ *
+ * @param start Beginning of the range.
+ * @param end End of the range.
+ * @param callable Callable to apply to every element of the range. See std::invoke
+ * requirements. Must be copiable.
+ * @param nThreads Number of threads to use.
+ *
+ */
+template <class It, class Callable>
+void parallelMap(It begin, It end, Callable callable, std::size_t nThreads) {
+ std::vector<std::thread> threads(nThreads);
+
+ std::mutex m;
+ for (auto &thread: threads) {
+ thread = std::thread([&m, &begin, end, callable]() {
+ while (true) {
+ decltype(begin) it;
+ {
+ std::scoped_lock lock(m);
+ if (begin == end) {
+ break;
+ }
+ it = begin++;
+ }
+ if (it != end) {
+ std::invoke(callable, *it);
+ }
+ }
+ });
+ }
+
+
+ // Join everything:
+ for (auto& t : threads) {
+ t.join();
+ }
+}
+
+}
+
+#endif