diff --git a/VERSION b/VERSION index 8bf83ecb..d093a126 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.0-beta.24 \ No newline at end of file +2.0.0-beta.25 \ No newline at end of file diff --git a/loader/include/Geode/utils/Task.hpp b/loader/include/Geode/utils/Task.hpp index 7aacd8f8..71868e20 100644 --- a/loader/include/Geode/utils/Task.hpp +++ b/loader/include/Geode/utils/Task.hpp @@ -6,8 +6,6 @@ #include "../loader/Loader.hpp" namespace geode { - extern std::atomic_size_t TASK_HANDLE_COUNT; - template <std::move_constructible T, std::move_constructible P = std::monostate> class [[nodiscard]] Task final { public: @@ -56,12 +54,12 @@ namespace geode { std::optional<T> m_resultValue; bool m_finalEventPosted = false; std::unique_ptr<void, void(*)(void*)> m_mapListener = { nullptr, +[](void*) {} }; - const char* m_whatIsThis = "Unk"; + std::string m_name; class PrivateMarker final {}; - static std::shared_ptr<Handle> create(const char* whatIsThis) { - return std::make_shared<Handle>(PrivateMarker(), whatIsThis); + static std::shared_ptr<Handle> create(std::string const& name) { + return std::make_shared<Handle>(PrivateMarker(), name); } bool is(Status status) { @@ -73,18 +71,7 @@ namespace geode { friend class Task; public: - std::string fmt() { - if (!this) return "null"; - return fmt::format("({} @ {})", fmt::ptr(this), m_whatIsThis); - } - - Handle(PrivateMarker, const char* whatIsThis) { - m_whatIsThis = whatIsThis; - log::info("create handle {}, {}", this->fmt(), ++TASK_HANDLE_COUNT); - } - ~Handle() { - log::info("destroy handle {}, {}", this->fmt(), --TASK_HANDLE_COUNT); - } + Handle(PrivateMarker, std::string const& name) : m_name(name) {} }; class Event final : public geode::Event { @@ -185,27 +172,16 @@ namespace geode { friend class Task; public: - Task() : m_handle(nullptr) { - log::info("create Task with handle {}", m_handle->fmt()); - } - ~Task() { - log::info("destroy Task with handle {}", m_handle->fmt()); - } + Task() : m_handle(nullptr) {} - Task(Task const& other) : m_handle(other.m_handle) { - log::info("copy Task with handle {}", m_handle->fmt()); - } - Task(Task&& other) : m_handle(std::move(other.m_handle)) { - log::info("move Task with handle {}", m_handle->fmt()); - } + Task(Task const& other) : m_handle(other.m_handle) {} + Task(Task&& other) : m_handle(std::move(other.m_handle)) {} Task& operator=(Task const& other) { m_handle = other.m_handle; - log::info("copy assign Task with handle {}", m_handle->fmt()); return *this; } Task& operator=(Task&& other) { m_handle = std::move(other.m_handle); - log::info("move assign Task with handle {}", m_handle->fmt()); return *this; } @@ -247,15 +223,15 @@ namespace geode { return m_handle && m_handle->is(Status::Cancelled); } - static Task immediate(T value) { - auto task = Task(Handle::create("Task::immediate")); + static Task immediate(T value, std::string const& name = "<Immediate Task>") { + auto task = Task(Handle::create(name)); Task::finish(task.m_handle, std::move(value)); return task; } - static Task run(Run&& body) { - auto task = Task(Handle::create("Task::run")); - std::thread([handle = std::weak_ptr(task.m_handle), body = std::move(body)] { - utils::thread::setName(fmt::format("Task @{}", fmt::ptr(handle.lock()))); + static Task run(Run&& body, std::string const& name = "<Task>") { + auto task = Task(Handle::create(name)); + std::thread([handle = std::weak_ptr(task.m_handle), name, body = std::move(body)] { + utils::thread::setName(fmt::format("Task '{}'", name)); auto result = body( [handle](P progress) { Task::progress(handle.lock(), std::move(progress)); @@ -276,10 +252,10 @@ namespace geode { }).detach(); return task; } - static Task runWithCallback(RunWithCallback&& body) { - auto task = Task(Handle::create("Task::runWithCallback")); - std::thread([handle = std::weak_ptr(task.m_handle), body = std::move(body)] { - utils::thread::setName(fmt::format("Task (w/ callback) @{}", fmt::ptr(handle.lock()))); + static Task runWithCallback(RunWithCallback&& body, std::string const& name = "<Callback Task>") { + auto task = Task(Handle::create(name)); + std::thread([handle = std::weak_ptr(task.m_handle), name, body = std::move(body)] { + utils::thread::setName(fmt::format("Task '{}'", name)); body( [handle](Result result) { if (result.isCancelled()) { @@ -304,11 +280,11 @@ namespace geode { } template <class ResultMapper, class ProgressMapper> - auto map(ResultMapper&& resultMapper, ProgressMapper&& progressMapper) { + auto map(ResultMapper&& resultMapper, ProgressMapper&& progressMapper, std::string const& name = "<Mapping Task>") { using T2 = decltype(resultMapper(std::declval<T*>())); using P2 = decltype(progressMapper(std::declval<P*>())); - auto task = Task<T2, P2>(Task<T2, P2>::Handle::create("Task::map")); + auto task = Task<T2, P2>(Task<T2, P2>::Handle::create(fmt::format("{} <= {}", name, m_handle->m_name))); // Lock the current task until we have managed to create our new one std::unique_lock<std::recursive_mutex> lock(m_handle->m_mutex); @@ -352,8 +328,8 @@ namespace geode { template <class ResultMapper> requires std::copy_constructible<P> - auto map(ResultMapper&& resultMapper) { - return this->map(std::move(resultMapper), +[](P* p) -> P { return *p; }); + auto map(ResultMapper&& resultMapper, std::string const& name = "<Mapping Task>") { + return this->map(std::move(resultMapper), +[](P* p) -> P { return *p; }, name); } ListenerResult handle(utils::MiniFunction<Callback> fn, Event* e) { diff --git a/loader/src/hooks/MenuLayer.cpp b/loader/src/hooks/MenuLayer.cpp index 03146e28..96ac2bc1 100644 --- a/loader/src/hooks/MenuLayer.cpp +++ b/loader/src/hooks/MenuLayer.cpp @@ -13,6 +13,7 @@ #include <loader/LoaderImpl.hpp> #include <loader/updater.hpp> #include <Geode/binding/ButtonSprite.hpp> +#include <Geode/modify/LevelSelectLayer.hpp> using namespace geode::prelude; diff --git a/loader/src/server/Server.cpp b/loader/src/server/Server.cpp index f2a95d94..29fd5025 100644 --- a/loader/src/server/Server.cpp +++ b/loader/src/server/Server.cpp @@ -110,6 +110,7 @@ public: using Value = typename Extract::Value; private: + std::mutex m_mutex; CacheMap<Query, ServerRequest<Value>> m_cache; public: @@ -118,6 +119,7 @@ public: FunCache(FunCache&&) = delete; ServerRequest<Value> get(Query const& query = Query()) { + std::unique_lock lock(m_mutex); if (auto v = m_cache.get(query)) { return *v; } @@ -126,12 +128,15 @@ public: return f; } size_t size() { + std::unique_lock lock(m_mutex); return m_cache.size(); } void limit(size_t size) { + std::unique_lock lock(m_mutex); m_cache.limit(size); } void clear() { + std::unique_lock lock(m_mutex); m_cache.clear(); } }; diff --git a/loader/src/ui/mods/ModsLayer.cpp b/loader/src/ui/mods/ModsLayer.cpp index 030cee4d..72e8b244 100644 --- a/loader/src/ui/mods/ModsLayer.cpp +++ b/loader/src/ui/mods/ModsLayer.cpp @@ -199,7 +199,7 @@ void ModsLayer::gotoTab(ModListSource* src) { else { this->addChild(m_lists.at(src)); } - + // Update current source m_currentSource = src; @@ -260,7 +260,9 @@ void ModsLayer::onTab(CCObject* sender) { } void ModsLayer::onRefreshList(CCObject*) { - m_lists.at(m_currentSource)->reloadPage(); + if (m_currentSource) { + m_lists.at(m_currentSource)->reloadPage(); + } } void ModsLayer::onBack(CCObject*) { @@ -323,10 +325,11 @@ ModsLayer* ModsLayer::scene() { } server::ServerRequest<std::vector<std::string>> ModsLayer::checkInstalledModsForUpdates() { - return server::checkUpdates(ranges::map<std::vector<std::string>>( + auto modIDs = ranges::map<std::vector<std::string>>( Loader::get()->getAllMods(), [](auto mod) { return mod->getID(); } - )).map([](auto* result) -> Result<std::vector<std::string>, server::ServerError> { + ); + return server::checkUpdates(modIDs).map([](auto* result) -> Result<std::vector<std::string>, server::ServerError> { if (result->isOk()) { std::vector<std::string> updatesFound; for (auto& update : result->unwrap()) { diff --git a/loader/src/ui/mods/sources/ModListSource.cpp b/loader/src/ui/mods/sources/ModListSource.cpp index bc5dfd5b..6c9f5721 100644 --- a/loader/src/ui/mods/sources/ModListSource.cpp +++ b/loader/src/ui/mods/sources/ModListSource.cpp @@ -189,6 +189,7 @@ InstalledModListSource::ProviderTask InstalledModListSource::fetchPage(size_t pa // If we're only checking mods that have updates, we first have to run // update checks every mod... if (m_query.onlyUpdates && content.mods.size()) { + // return ProviderTask::immediate(Ok(content)); return ProviderTask::runWithCallback([content, query = m_query](auto finish, auto progress, auto hasBeenCancelled) { struct Waiting final { ModListSource::ProvidedMods content; @@ -205,6 +206,13 @@ InstalledModListSource::ProviderTask InstalledModListSource::fetchPage(size_t pa [waiting, finish, query](auto* result) { waiting->waitingFor -= 1; if (waiting->waitingFor == 0) { + // Make sure to clear our waiting tasks vector so + // we don't have a funky lil circular ref and a + // memory leak! + waiting->waitingTasks.clear(); + + // Filter the results based on the current search + // query and return them filterModsWithQuery(waiting->content, query); finish(Ok(std::move(waiting->content))); } @@ -388,5 +396,3 @@ void clearAllModListSourceCaches() { ModPackListSource::get()->clearCache(); } - -std::atomic_size_t geode::TASK_HANDLE_COUNT = 0; diff --git a/loader/src/ui/mods/sources/ModSource.cpp b/loader/src/ui/mods/sources/ModSource.cpp index a7e20699..8469c1f2 100644 --- a/loader/src/ui/mods/sources/ModSource.cpp +++ b/loader/src/ui/mods/sources/ModSource.cpp @@ -150,9 +150,6 @@ server::ServerRequest<std::optional<server::ServerModUpdate>> ModSource::checkUp return Ok(std::nullopt); } return Err(result->unwrapErr()); - }, - [](server::ServerProgress* progress) { - return *progress; } ); } diff --git a/loader/src/ui/mods/test/UITest.cpp b/loader/src/ui/mods/test/UITest.cpp index fec21388..0e9e55e0 100644 --- a/loader/src/ui/mods/test/UITest.cpp +++ b/loader/src/ui/mods/test/UITest.cpp @@ -6,6 +6,7 @@ #include <Geode/ui/BasedButtonSprite.hpp> #include <Geode/utils/web2.hpp> #include <server/Server.hpp> +#include "../sources/ModListSource.hpp" using namespace geode::prelude; @@ -156,7 +157,8 @@ protected: m_serListener.getFilter().cancel(); } void onServerCacheClear(CCObject*) { - server::clearServerCaches(); + server::clearServerCaches(true); + clearAllModListSourceCaches(); } public: diff --git a/loader/src/utils/web2.cpp b/loader/src/utils/web2.cpp index 03aa3dba..1862b0d8 100644 --- a/loader/src/utils/web2.cpp +++ b/loader/src/utils/web2.cpp @@ -282,7 +282,7 @@ WebTask WebRequest::send(std::string_view method, std::string_view url) { // Otherwise resolve with success :-) return std::move(responseData.response); - }); + }, fmt::format("{} request to {}", method, url)); } WebTask WebRequest::post(std::string_view url) { return this->send("POST", url);