dispatcher

This commit is contained in:
camila314 2022-05-31 00:11:16 -05:00
parent 8fe349d259
commit 19d4f3bbae
5 changed files with 71 additions and 245 deletions

View file

@ -5,6 +5,6 @@
#include "syntax/Field.hpp"
#include "syntax/InternalMacros.hpp"
#include "loader/GeodeLoader.hpp"
#include "loader/API.hpp"
#include "loader/Dispatcher.hpp"
using namespace geode::modifier;

View file

@ -1,3 +1,5 @@
#pragma once
#include "../codegen-base/Macros.hpp"
#include "../utils/include.hpp"
#include "Mod.hpp"
@ -6,65 +8,86 @@
#include <vector>
namespace geode {
class Dispatcher;
struct GEODE_DLL dispatch_handle {
void* handle;
class Dispatcher;
struct GEODE_DLL dispatch_handle {
void* handle;
dispatch_handle() = delete;
dispatch_handle(dispatch_handle&& d) : handle(d.handle) {}
dispatch_handle(dispatch_handle const& d) : handle(d.handle) {}
dispatch_handle() = delete;
dispatch_handle(dispatch_handle const& d) : handle(d.handle) {}
template <typename T>
std::function<T> get() {
*reinterpret_cast<std::function<T>*>(this->handle);
}
template <typename T>
std::function<T> into() {
*reinterpret_cast<std::function<T>*>(this->handle);
}
template <typename R, typename ...Args>
R call(Args... args) {
return this->get<std::function<R(Args...)>>()(args...);
}
private:
dispatch_handle(void* h) : handle(h) {}
friend class Dispatcher;
};
template <typename R, typename ...Args>
R call(Args... args) {
return this->into<std::function<R(Args...)>>()(args...);
}
class GEODE_DLL Dispatcher {
protected:
std::map<dispatch_handle, std::pair<std::string, Mod*>> m_dispatchMap;
std::map<std::string, std::vector<dispatch_handle>> m_selectorMap;
// 2 maps for lookup speed
bool operator<(dispatch_handle const& b) const {
return handle < b.handle;
}
std::vector<dispatch_handle> _getHandles(std::string const& a);
std::pair<string, Mod*> _getInfo(dispatch_handle u);
bool operator==(dispatch_handle const& b) const {
return handle == b.handle;
}
private:
dispatch_handle(void* h) : handle(h) {}
void _removeFunction(dispatch_handle u);
dispatch_handle _addFunction(Mod* m, std::string const& a);
template <typename T>
static dispatch_handle from(std::function<T> f) {
return dispatch_handle(reinterpret_cast<void*>(new std::function<T>(f)));
}
friend class Dispatcher;
};
std::vector<dispatch_handle> _allHandles();
class GEODE_DLL Dispatcher {
protected:
std::map<dispatch_handle, std::pair<std::string, Mod*>> m_dispatchMap;
std::map<std::string, std::vector<dispatch_handle>> m_selectorMap;
// 2 maps for lookup speed
std::vector<dispatch_handle> getFunctions_(std::string const& a);
void addFunction_(Mod* m, std::string const& a, dispatch_handle u);
std::vector<dispatch_handle> allFunctions_();
template <typename T>
std::function<T> _fromOpaque(void* f) {
*reinterpret_cast<std::function<T>*>(f);
}
Dispatcher() {}
template <typename T>
void* _toOpaque(std::function<T> f) {
return reinterpret_cast<void*>(new std::function<T>(f));
}
public:
static Dispatcher* get();
public:
static Dispatcher* get();
template <typename T>
std::vector<std::function<T>> getSelectors(std::string_view const& a) {
return geode::vector_utils::map(_getSelectors(a), [this](std::pair<dispatch_handle, void*> selector) {
return _fromOpaque<T>(selector.second);
});
}
template <typename T>
std::vector<std::function<T>> getFunctions(std::string const& a) {
return geode::vector_utils::map(getFunctions_(a), [this](dispatch_handle fn) {
return fn.into<T>();
});
}
};
template <typename T>
std::function<T> getFunction(std::string const& a) {
return getFunctions_(a).back().into<T>();
}
template <typename T>
dispatch_handle addFunction(std::string const& a, std::function<T> f) {
dispatch_handle hdl = dispatch_handle::from(f);
addFunction_(Mod::get(), a, hdl);
return hdl;
}
template <typename T>
std::vector<dispatch_handle> allFunctions() {
return geode::vector_utils::map(allFunctions_(), [this](dispatch_handle fn) {
return fn.into<T>();
});
}
void removeFunction(dispatch_handle u);
std::pair<std::string, Mod*> getFunctionInfo(dispatch_handle u);
};
}

View file

@ -1,148 +0,0 @@
#pragma once
#include <string>
#include <typeinfo>
#include <memory>
#include <exception>
#include <map>
#include <Macros.hpp>
#include <any>
#include <variant>
#ifndef GEODE_DLL
#define GEODE_DLL
#endif
namespace geode {
class EventCenter;
class Mod;
template <typename T = std::monostate>
struct EventInfo {
std::string selector;
inline EventInfo(std::string sel) : selector(sel) {}
inline EventInfo() {}
};
template <typename T = std::monostate>
struct ConstEventInfo {
char const* selector;
inline constexpr ConstEventInfo(char const* sel) : selector(sel) {}
inline constexpr ConstEventInfo() {}
inline operator EventInfo<T>() {
return EventInfo<T>(selector);
}
};
template <typename T = std::monostate>
class Event {
protected:
EventInfo<T> m_info;
T m_object;
Mod* m_sender;
public:
inline T const& object() const {
return m_object;
}
inline std::string const& selector() const { return m_info.selector; }
inline Mod* sender() const { return m_sender; }
inline Event(EventInfo<T> inf, T obj, Mod* sender) :
m_info(inf),
m_object(obj),
m_sender(sender) {}
inline Event(std::string sel, T obj, Mod* sender) : Event(EventInfo<T>(sel), obj, sender) {}
inline Event(std::string sel, Mod* sender) : Event(sel, T(), sender) {}
inline Event(EventInfo<T> inf, Mod* sender) : Event(inf, T(), sender) {}
// Event(std::string sel) : Event(sel, Interface::get()->mod()) {}
inline Event(Event&& a) : m_info(a.m_info), m_sender(a.m_sender), m_object(std::move(a.m_object)) {}
inline operator T() { return m_object; }
friend class EventCenter;
};
template <typename T = std::monostate>
struct Observer {
EventInfo<T> m_info;
Mod* m_mod;
std::function<void(Event<T> const&)> m_callback;
template <typename U = std::monostate>
inline Observer<U>* into() {
return reinterpret_cast<Observer<U>*>(this);
}
};
class GEODE_DLL EventCenter {
public:
std::map<Mod*, std::map<std::string, std::vector<Observer<std::monostate>*>>> m_observers;
static EventCenter* shared;
public:
EventCenter();
static EventCenter* get();
template <typename T>
void send(Event<T> n, Mod* m) {
for (auto& obs : m_observers[m][n.selector()]) {
obs->template into<T>()->m_callback(n);
}
}
template <typename T>
void broadcast(Event<T> n) {
for (auto& [k, v] : m_observers) {
for (auto& obs : v[n.selector()]) {
obs->template into<T>()->m_callback(n);
}
}
}
template <typename T = std::monostate>
Observer<std::monostate>* registerObserver(Mod* m, EventInfo<T> info, std::function<void(Event<T> const&)> cb) {
Observer<T>* ob = new Observer<T>;
ob->m_info = info;
ob->m_callback = cb;
ob->m_mod = m;
m_observers[m][info.selector].push_back(ob->into());
return ob->into();
}
template <typename T = std::monostate>
Observer<std::monostate>* registerObserver(Mod* m, std::string sel, std::function<void(Event<T> const&)> cb) {
return registerObserver(m, EventInfo<T>(sel), cb);
}
template <typename T = std::monostate>
inline Observer<std::monostate>* registerObserver(std::string sel, std::function<void(Event<T> const&)> cb);
template <typename T = std::monostate>
inline Observer<std::monostate>* registerObserver(EventInfo<T> info, std::function<void(Event<T> const&)> cb);
void unregisterObserver(Observer<std::monostate>* ob);
std::vector<Observer<std::monostate>*> getObservers(std::string selector, Mod* m);
};
}
#define _$observe3(sel, T, data, ctr) \
void $_observer##ctr(geode::Event<T> const&); \
static auto $_throw##ctr = (([](){ \
geode::Interface::get()->scheduleOnLoad(+[](Mod* m) { \
geode::EventCenter::get()->registerObserver<T>( \
m, sel, $_observer##ctr \
); \
}); \
})(), 0); \
void $_observer##ctr(geode::Event<T> const& data)
#define _$observe1(sel, ctr) _$observe3(sel, std::monostate, , ctr)
#define $observe(...) GEODE_INVOKE(GEODE_CONCAT(_$observe, GEODE_NUMBER_OF_ARGS(__VA_ARGS__)), __VA_ARGS__, __COUNTER__)

View file

@ -59,15 +59,9 @@ namespace geode {
using loadfn_t = void(*)(Mod*);
struct ScheduledExport {
std::string m_selector;
std::variant<unknownmemfn_t, unknownfn_t> m_func;
};
Mod* m_mod = nullptr;
std::vector<ScheduledHook> m_scheduledHooks;
std::vector<ScheduledLog> m_scheduledLogs;
std::vector<ScheduledExport> m_scheduledExports;
std::vector<loadfn_t> m_scheduledFunctions;
public:
@ -160,17 +154,6 @@ namespace geode {
inline Log Log::get() {
return Mod::get()->log();
}
template <typename T>
inline Observer<std::monostate>* EventCenter::registerObserver(std::string sel, std::function<void(Event<T> const&)> cb) {
return registerObserver(Mod::get(), EventInfo<T>(sel), cb);
}
template <typename T>
inline Observer<std::monostate>* EventCenter::registerObserver(EventInfo<T> info, std::function<void(Event<T> const&)> cb) {
return registerObserver(Mod::get(), info, cb);
}
}
inline const char* operator"" _spr(const char* str, size_t) {

View file

@ -3,7 +3,6 @@
#include <Macros.hpp>
#include "Types.hpp"
#include "Hook.hpp"
#include "Event.hpp"
#include "../utils/types.hpp"
#include "../utils/Result.hpp"
#include "../utils/VersionInfo.hpp"
@ -335,37 +334,6 @@ namespace geode {
Severity severity
);
/**
* Exports an internal function. You can use this
* for mod interoperability.
* @param selector mod-specific string identifier
* for your function
* @param ptr pointer to your exported function
*/
template <typename T>
void exportAPIFunction(std::string const& selector, T ptr) {
EventCenter::get()->registerObserver<T*>(this, selector, [ptr](Event<T*> const& n) {
//*reinterpret_cast<T*>(n.object<void*>()) = ptr;
*n.object() = ptr;
});
}
/**
* Imports an internal function. You can use this
* for mod interoperability.
* @param selector Mod-specific string identifier
* for your function
* @param source Mod that the API function originates
* from
* @returns Pointer to the external function
*/
template <typename T>
T importAPIFunction(std::string const& selector, Mod* source) {
T out;
EventCenter::get()->send(Event(selector, &out, nullptr), source);
return out;
}
/**
* Get all hooks owned by this Mod
* @returns Vector of hooks