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