sandbox
Loading...
Searching...
No Matches
module.hpp
1#ifndef LIBSBX_CORE_MODULE_HPP_
2#define LIBSBX_CORE_MODULE_HPP_
3
4#include <type_traits>
5#include <unordered_set>
6#include <unordered_map>
7#include <typeindex>
8#include <functional>
9#include <memory>
10#include <cinttypes>
11#include <cmath>
12
13#include <libsbx/utility/noncopyable.hpp>
14
15namespace sbx::core {
16
17template<typename Derived, typename Base>
18concept derived_from = std::is_base_of_v<Base, Derived>;
19
21
22 template<typename>
23 friend class module;
24
25 friend class engine;
26
27public:
28
29 module_manager() = delete;
30
31 ~module_manager() = default;
32
33private:
34
35 enum class stage : std::uint8_t {
36 pre,
37 normal,
38 post,
39 fixed,
40 rendering,
41 }; // enum class stage
42
43 template<typename... Types>
44 struct dependencies {
45 auto get() const noexcept -> std::unordered_set<std::type_index> {
46 auto types = std::unordered_set<std::type_index>{};
47 (types.insert(std::type_index{typeid(Types)}), ...);
48 return types;
49 }
50 }; // struct dependencies
51
52 struct module_base {
53 virtual ~module_base() = default;
54 virtual auto update() -> void = 0;
55 }; // struct module_base
56
57 struct module_factory {
58 module_manager::stage stage{};
59 std::unordered_set<std::type_index> dependencies{};
60 std::function<module_base*()> create{};
61 std::function<void(module_base*)> destroy{};
62 }; // module_factory
63
64 static auto _factories() -> std::unordered_map<std::type_index, module_factory>& {
65 static auto instance = std::unordered_map<std::type_index, module_factory>{};
66 return instance;
67 }
68
69}; // class module_manager
70
71template<typename Derived>
72class module : public module_manager::module_base, public utility::noncopyable {
73
74public:
75
76 virtual ~module() {
77 static_assert(!std::is_abstract_v<Derived>, "Class may not be abstract.");
78 static_assert(std::is_base_of_v<module<Derived>, Derived>, "Class must inherit from module<Class>.");
79 }
80
81protected:
82
83 using base_type = module_manager::module_base;
84
85 template<typename... Dependencies>
86 using dependencies = module_manager::dependencies<Dependencies...>;
87
88 using stage = module_manager::stage;
89
90 template<derived_from<base_type>... Dependencies>
91 static auto register_module(stage stage, dependencies<Dependencies...>&& dependencies = {}) -> bool {
92 module_manager::_factories().insert({std::type_index{typeid(Derived)}, module_manager::module_factory{
93 .stage = stage,
94 .dependencies = dependencies.get(),
95 .create = [](){
96 auto* instance = reinterpret_cast<Derived*>(std::malloc(sizeof(Derived)));
97
98 if (!instance) {
99 throw std::bad_alloc{};
100 }
101
102 std::construct_at(instance);
103
104 return instance;
105 },
106 .destroy = [](module_base* instance){
107 std::destroy_at(reinterpret_cast<Derived*>(instance));
108 std::free(instance);
109 }
110 }});
111
112 return true;
113 }
114
115}; // class module
116
117} // namespace sbx::core
118
119#endif // LIBSBX_CORE_MODULE_HPP_
Definition: engine.hpp:27
Definition: module.hpp:20
Definition: module.hpp:72
Definition: noncopyable.hpp:6