remove schedules, also make Mod::get() lazy

This commit is contained in:
altalk23 2022-12-13 12:23:37 +03:00
parent 87b8138433
commit 5e1d1eccdb
22 changed files with 124 additions and 129 deletions

View file

@ -3,7 +3,6 @@
#include <Geode/loader/Mod.hpp>
GEODE_API void GEODE_CALL geode_implicit_load(geode::Mod* m) {
geode::Mod::setSharedMod(m);
geode::log::Logger::runScheduled(m);
geode::Loader::get()->dispatchScheduledFunctions(m);
// geode::Mod::setSharedMod(m);
// geode::Loader::get()->dispatchScheduledFunctions(m);
}

View file

@ -175,10 +175,7 @@ namespace cocos2d::extension {}
struct GEODE_CONCAT(ExecFuncUnique, __LINE__) {}; \
} \
static inline auto GEODE_CONCAT(Exec, __LINE__) = \
(Loader::get()->scheduleOnModLoad( \
getMod(), \
&GEODE_CONCAT(geodeExecFunction, __LINE__) < GEODE_CONCAT(ExecFuncUnique, __LINE__) > \
), \
(GEODE_CONCAT(geodeExecFunction, __LINE__) < GEODE_CONCAT(ExecFuncUnique, __LINE__) > (), \
0); \
template <class> \
void GEODE_CONCAT(geodeExecFunction, __LINE__)()

View file

@ -113,7 +113,7 @@ namespace geode {
class GEODE_DLL [[nodiscard]] Event {
private:
static std::unordered_set<EventListenerProtocol*> s_listeners;
static std::unordered_set<EventListenerProtocol*>& listeners();
friend EventListenerProtocol;
public:

View file

@ -64,11 +64,9 @@ namespace geode {
template<class = void>
std::monostate listenForIPC(std::string const& messageID, nlohmann::json(*callback)(IPCEvent*)) {
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
new EventListener(
(void) new EventListener(
callback, IPCFilter(getMod()->getID(), messageID)
);
});
return std::monostate();
}
}

View file

@ -37,6 +37,8 @@ namespace geode {
Result<Mod*> loadModFromInfo(ModInfo const& info);
Mod* takeNextMod();
public:
// TODO: do we want to expose all of these functions?
static Loader* get();
@ -64,7 +66,6 @@ namespace geode {
void updateResources();
void queueInGDThread(ScheduledFunction func);
void scheduleOnModLoad(Mod* mod, ScheduledFunction func);
void waitForModsToBeLoaded();
/**
@ -79,5 +80,16 @@ namespace geode {
bool didLastLaunchCrash() const;
friend class LoaderImpl;
friend Mod* takeNextLoaderMod();
};
/**
* @brief Take the next mod to load
*
* @return Mod* The next mod to load
*/
inline GEODE_HIDDEN Mod* takeNextLoaderMod() {
return Loader::get()->takeNextMod();
}
}

View file

@ -114,40 +114,22 @@ namespace geode {
Logger() = delete;
~Logger() = delete;
// Unscheduled logs
// logs
static void _push(Log&& log);
// Scheduled functions
template <class = void>
static inline std::vector<Log>& scheduled() {
static std::vector<Log> scheduledLogs;
return scheduledLogs;
}
static void run(Mod* m, std::vector<Log>& scheduled);
public:
static void setup();
static inline void push(Log&& log) {
if (log.m_sender == nullptr)
Logger::scheduled().push_back(std::move(log));
else
Logger::_push(std::move(log));
}
static inline void pop(Log* log) {
if (log->m_sender == nullptr)
geode::utils::ranges::remove(Logger::scheduled(), *log);
else
geode::utils::ranges::remove(Logger::s_logs, *log);
}
static std::vector<Log*> list();
static void clear();
static inline void runScheduled(Mod* m) {
Logger::run(m, Logger::scheduled());
}
};
template <typename... Args>

View file

@ -31,6 +31,8 @@ namespace geode {
~HandleToSaved();
};
inline GEODE_HIDDEN Mod* takeNextLoaderMod();
/**
* @class Mod
* Represents a Mod ingame.
@ -225,6 +227,9 @@ namespace geode {
*/
template <class = void>
static inline GEODE_HIDDEN Mod* get() {
if (!sharedMod<>) {
sharedMod<> = takeNextLoaderMod();
}
return sharedMod<>;
}

View file

@ -47,13 +47,9 @@ void GEODE_CONCAT(geodeExecFunction, __LINE__)(ModStateEvent*); \
namespace { \
struct GEODE_CONCAT(ExecFuncUnique, __LINE__) {}; \
} \
static inline auto GEODE_CONCAT(Exec, __LINE__) = (geode::Loader::get()->scheduleOnModLoad(\
geode::Mod::get(), []() { \
new geode::EventListener( \
static inline auto GEODE_CONCAT(Exec, __LINE__) = (new geode::EventListener( \
&GEODE_CONCAT(geodeExecFunction, __LINE__)<GEODE_CONCAT(ExecFuncUnique, __LINE__)>,\
geode::ModStateFilter(geode::Mod::get(), geode::ModEventType::type)\
); \
} \
), 0); \
template<class> \
void GEODE_CONCAT(geodeExecFunction, __LINE__)(ModStateEvent*)

View file

@ -56,20 +56,16 @@ namespace geode {
std::monostate listenForSettingChanges(
std::string const& settingID, void (*callback)(T*)
) {
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
new EventListener(
(void)new EventListener(
callback, SettingChangedFilter<T>(getMod()->getID(), settingID)
);
});
return std::monostate();
}
static std::monostate listenForAllSettingChanges(void (*callback)(Setting*)) {
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
new EventListener(
(void)new EventListener(
callback, SettingChangedFilter(getMod()->getID())
);
});
return std::monostate();
}
}

View file

@ -30,9 +30,7 @@ namespace geode::modifier {
public:
// unordered_map<handles> idea
ModifyBase() {
Loader::get()->scheduleOnModLoad(getMod(), []() {
Derived::apply();
});
}
template <class, class>
friend class ModifyDerive;

View file

@ -26,7 +26,7 @@ if (GEODE_TARGET_PLATFORM STREQUAL "iOS")
target_link_libraries(lilac_hook "-F ${CMAKE_CURRENT_SOURCE_DIR}/../ios -framework CydiaSubstrate")
endif()
target_compile_features(lilac_hook PUBLIC cxx_std_17)
target_compile_features(lilac_hook PUBLIC cxx_std_20)
target_include_directories(lilac_hook
PRIVATE
${lilac_SOURCE_DIR}/include/geode/core/hook

View file

@ -42,15 +42,12 @@ static ModInfo getInternalModInfo() {
}
}
InternalMod::InternalMod() : Mod(getInternalModInfo()) {
InternalMod::InternalMod() : Mod(ModInfo()) {}
void InternalMod::setModInfo() {
m_info = getInternalModInfo();
m_saveDirPath = dirs::getModsSaveDir() / m_info.id;
ghc::filesystem::create_directories(m_saveDirPath);
auto sett = this->loadData();
if (!sett) {
log::internalLog(Severity::Error, this, "{}", sett.unwrapErr());
}
}
InternalMod::~InternalMod() {}

View file

@ -13,4 +13,6 @@ protected:
public:
static InternalMod* get();
void setModInfo();
};

View file

@ -2,14 +2,12 @@
USE_GEODE_NAMESPACE();
std::unordered_set<EventListenerProtocol*> Event::s_listeners = {};
void EventListenerProtocol::enable() {
Event::s_listeners.insert(this);
Event::listeners().insert(this);
}
void EventListenerProtocol::disable() {
Event::s_listeners.erase(this);
Event::listeners().erase(this);
}
EventListenerProtocol::~EventListenerProtocol() {
@ -21,9 +19,14 @@ Event::~Event() {}
void Event::postFrom(Mod* m) {
if (m) this->sender = m;
for (auto h : Event::s_listeners) {
for (auto h : Event::listeners()) {
if (h->passThrough(this) == ListenerResult::Stop) {
break;
}
}
}
std::unordered_set<EventListenerProtocol*>& Event::listeners() {
static std::unordered_set<EventListenerProtocol*> listeners;
return listeners;
}

View file

@ -21,10 +21,6 @@ void Loader::addSearchPaths() {
return m_impl->addSearchPaths();
}
void Loader::dispatchScheduledFunctions(Mod* mod) {
return m_impl->dispatchScheduledFunctions(mod);
}
Result<Mod*> Loader::loadModFromInfo(ModInfo const& info) {
return m_impl->loadModFromInfo(info);
}
@ -105,10 +101,6 @@ void Loader::queueInGDThread(ScheduledFunction func) {
return m_impl->queueInGDThread(func);
}
void Loader::scheduleOnModLoad(Mod* mod, ScheduledFunction func) {
return m_impl->scheduleOnModLoad(mod, func);
}
void Loader::waitForModsToBeLoaded() {
return m_impl->waitForModsToBeLoaded();
}
@ -124,3 +116,7 @@ void Loader::closePlatformConsole() {
bool Loader::didLastLaunchCrash() const {
return m_impl->didLastLaunchCrash();
}
Mod* Loader::takeNextMod() {
return m_impl->takeNextMod();
}

View file

@ -245,22 +245,6 @@ Mod* Loader::Impl::getLoadedMod(std::string const& id) const {
return nullptr;
}
void Loader::Impl::dispatchScheduledFunctions(Mod* mod) {
std::lock_guard _(m_scheduledFunctionsMutex);
for (auto& func : m_scheduledFunctions) {
func();
}
m_scheduledFunctions.clear();
}
void Loader::Impl::scheduleOnModLoad(Mod* mod, ScheduledFunction func) {
std::lock_guard _(m_scheduledFunctionsMutex);
if (mod) {
return func();
}
m_scheduledFunctions.push_back(func);
}
void Loader::Impl::updateModResources(Mod* mod) {
if (!mod->m_info.spritesheets.size()) {
return;
@ -594,3 +578,44 @@ ListenerResult ResourceDownloadFilter::handle(
}
ResourceDownloadFilter::ResourceDownloadFilter() {}
void Loader::Impl::provideNextMod(Mod* mod) {
m_nextModLock.lock();
m_nextMod = mod;
}
Mod* Loader::Impl::takeNextMod() {
if (!m_nextMod) {
// this means we're hopefully loading the internal mod
// TODO: make this less hacky
auto res = this->setupInternalMod();
if (!res) {
log::error("{}", res.unwrapErr());
return nullptr;
}
return m_nextMod;
}
auto ret = m_nextMod;
m_nextModCV.notify_all();
return ret;
}
void Loader::Impl::releaseNextMod() {
auto lock = std::unique_lock<std::mutex>(m_nextModAccessMutex);
m_nextModCV.wait(lock);
m_nextModLock.unlock();
}
Result<> Loader::Impl::setupInternalMod() {
this->provideNextMod(InternalMod::get());
(void)Mod::get();
m_nextModLock.unlock();
InternalMod::get()->setModInfo();
auto sett = Mod::get()->loadData();
if (!sett) {
log::error("{}", sett.unwrapErr());
}
return Ok();
}

View file

@ -46,8 +46,6 @@ public:
std::vector<InvalidGeodeFile> m_invalidMods;
std::unordered_map<std::string, Mod*> m_mods;
std::vector<ghc::filesystem::path> m_texturePaths;
std::vector<ScheduledFunction> m_scheduledFunctions;
mutable std::mutex m_scheduledFunctionsMutex;
bool m_isSetup = false;
std::condition_variable m_earlyLoadFinishedCV;
@ -59,6 +57,18 @@ public:
std::vector<std::pair<Hook*, Mod*>> m_internalHooks;
bool m_readyToHook = false;
std::mutex m_nextModMutex;
std::unique_lock<std::mutex> m_nextModLock = std::unique_lock<std::mutex>(m_nextModMutex, std::defer_lock);
std::condition_variable m_nextModCV;
std::mutex m_nextModAccessMutex;
Mod* m_nextMod = nullptr;
Result<> setupInternalMod();
void provideNextMod(Mod* mod);
Mod* takeNextMod();
void releaseNextMod();
void downloadLoaderResources();
bool loadHooks();
@ -72,7 +82,6 @@ public:
void updateModResources(Mod* mod);
void addSearchPaths();
void dispatchScheduledFunctions(Mod* mod);
friend void GEODE_CALL ::geode_implicit_load(Mod*);
Result<Mod*> loadModFromInfo(ModInfo const& info);
@ -102,7 +111,6 @@ public:
void updateResources();
void scheduleOnModLoad(Mod* mod, ScheduledFunction func);
void waitForModsToBeLoaded();
bool didLastLaunchCrash() const;

View file

@ -106,7 +106,7 @@ std::string Log::toString(bool logTime) const {
res += fmt::format("{:%H:%M:%S}", m_time);
}
res += fmt::format(" [{}]: ", m_sender ? m_sender->getName() : "?");
res += fmt::format(" [{}]: ", m_sender ? m_sender->getName() : "Geode?");
for (auto& i : m_components) {
res += i->_toString();
@ -209,15 +209,6 @@ void Logger::clear() {
s_logs.clear();
}
void Logger::run(Mod* m, std::vector<Log>& scheduled) {
for (auto&& log : scheduled) {
log.m_sender = m;
Logger::_push(std::move(log));
}
scheduled.clear();
}
// Misc
std::string geode::log::generateLogName() {

View file

@ -203,6 +203,8 @@ Result<> Mod::loadBinary() {
return Err("Mod has unresolved dependencies");
}
LoaderImpl::get()->provideNextMod(this);
GEODE_UNWRAP(this->loadPlatformBinary());
m_binaryLoaded = true;

View file

@ -147,16 +147,6 @@ static auto $_ = listenForIPC("list-mods", [](IPCEvent* event) -> nlohmann::json
int geodeEntry(void* platformData) {
// setup internals
if (!Loader::get()) {
LoaderImpl::get()->platformMessageBox(
"Unable to Load Geode!",
"There was an unknown fatal error setting up "
"internal tools and Geode can not be loaded. "
"(Loader::get returned nullptr)"
);
return 1;
}
if (!geode::core::hook::initialize()) {
LoaderImpl::get()->platformMessageBox(
"Unable to load Geode!",
@ -167,8 +157,6 @@ int geodeEntry(void* platformData) {
return 1;
}
geode_implicit_load(InternalMod::get());
// set up loader, load mods, etc.
if (!LoaderImpl::get()->setup()) {
LoaderImpl::get()->platformMessageBox(

View file

@ -1,5 +1,5 @@
{
"geode": "0.4.1",
"geode": "0.6.1",
"version": "1.0.0",
"id": "geode.testdep",
"name": "Geode Test Dependency",

View file

@ -1,5 +1,5 @@
{
"geode": "0.4.1",
"geode": "0.6.1",
"version": "1.0.0",
"id": "geode.test",
"name": "Geode Test",