fix all remaining memory issues with Task <3

This commit is contained in:
HJfod 2024-04-22 18:16:26 +03:00
parent 18bb4436fd
commit 72be477f48
9 changed files with 47 additions and 57 deletions

View file

@ -1 +1 @@
2.0.0-beta.24
2.0.0-beta.25

View file

@ -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) {

View file

@ -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;

View file

@ -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();
}
};

View file

@ -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()) {

View file

@ -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;

View file

@ -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;
}
);
}

View file

@ -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:

View file

@ -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);