mirror of
https://github.com/geode-sdk/geode.git
synced 2025-03-28 13:52:07 -04:00
fix all remaining memory issues with Task <3
This commit is contained in:
parent
18bb4436fd
commit
72be477f48
9 changed files with 47 additions and 57 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2.0.0-beta.24
|
||||
2.0.0-beta.25
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue