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#include <optional>
13
14#include <libsbx/utility/noncopyable.hpp>
15#include <libsbx/utility/type_id.hpp>
16
17namespace sbx::core {
18
19namespace detail {
20
22
23} // namespace detail
24
30template<typename Type>
32
33template<typename Derived, typename Base>
34concept derived_from = std::is_base_of_v<Base, Derived>;
35
37
38 template<typename>
39 friend class module;
40
41 friend class engine;
42
43public:
44
45 module_manager() = delete;
46
47 ~module_manager() = default;
48
49private:
50
51 enum class stage : std::uint8_t {
52 pre,
53 normal,
54 post,
55 pre_fixed,
56 fixed,
57 post_fixed,
58 rendering
59 }; // enum class stage
60
61 template<typename... Types>
62 struct dependencies {
63 auto get() const noexcept -> std::unordered_set<std::uint32_t> {
64 auto types = std::unordered_set<std::uint32_t>{};
65 (types.insert(utility::type_id<Types>::value()), ...);
66 return types;
67 }
68 }; // struct dependencies
69
70 struct module_base {
71 virtual ~module_base() = default;
72 virtual auto update() -> void = 0;
73 }; // struct module_base
74
75 struct module_factory {
76 module_manager::stage stage{};
77 std::unordered_set<std::uint32_t> dependencies{};
78 std::function<module_base*()> create{};
79 std::function<void(module_base*)> destroy{};
80 }; // module_factory
81
82 static auto _factories() -> std::vector<std::optional<module_factory>>& {
83 static auto instance = std::vector<std::optional<module_factory>>{};
84 return instance;
85 }
86
87}; // class module_manager
88
89template<typename Derived>
90class module : public module_manager::module_base, public utility::noncopyable {
91
92public:
93
94 virtual ~module() {
95 static_assert(!std::is_abstract_v<Derived>, "Class may not be abstract.");
96 static_assert(std::is_base_of_v<module<Derived>, Derived>, "Class must inherit from module<Class>.");
97 }
98
99protected:
100
101 using base_type = module_manager::module_base;
102
103 template<typename... Dependencies>
104 using dependencies = module_manager::dependencies<Dependencies...>;
105
106 using stage = module_manager::stage;
107
108 template<derived_from<base_type>... Dependencies>
109 static auto register_module(stage stage, dependencies<Dependencies...>&& dependencies = {}) -> bool {
110 const auto type = type_id<Derived>::value();
111
112 auto& factories = module_manager::_factories();
113
114 factories.resize(std::max(factories.size(), static_cast<std::size_t>(type + 1u)));
115
116 factories[type] = module_manager::module_factory{
117 .stage = stage,
118 .dependencies = dependencies.get(),
119 .create = [](){
120 auto* instance = reinterpret_cast<Derived*>(std::malloc(sizeof(Derived)));
121
122 if (!instance) {
123 throw std::bad_alloc{};
124 }
125
126 std::construct_at(instance);
127
128 return instance;
129 },
130 .destroy = [](module_base* instance){
131 std::destroy_at(reinterpret_cast<Derived*>(instance));
132 std::free(instance);
133 }
134 };
135
136 return true;
137 }
138
139}; // class module
140
141} // namespace sbx::core
142
143#endif // LIBSBX_CORE_MODULE_HPP_
Definition: engine.hpp:34
Definition: module.hpp:36
Definition: module.hpp:90
Definition: module.hpp:21
Definition: noncopyable.hpp:6
A scoped type ID generator. Allows for generating unique IDs for types within a specific scope.
Definition: type_id.hpp:30
static auto value() noexcept -> std::uint32_t
Generates a unique ID for the type.
Definition: type_id.hpp:40