added monostate (built-in config system)
This commit is contained in:
24
README.md
24
README.md
@@ -43,6 +43,7 @@
|
||||
* [Compile-time identifiers](#compile-time-identifiers)
|
||||
* [Runtime identifiers](#runtime-identifiers)
|
||||
* [Hashed strings](#hashed-strings)
|
||||
* [Monostate](#monostate)
|
||||
* [Crash Course: service locator](#crash-course-service-locator)
|
||||
* [Crash Course: cooperative scheduler](#crash-course-cooperative-scheduler)
|
||||
* [The process](#the-process)
|
||||
@@ -1697,6 +1698,29 @@ and over which users have not the control. Choosing a slightly different
|
||||
identifier is probably the best solution to make the conflict disappear in this
|
||||
case.
|
||||
|
||||
## Monostate
|
||||
|
||||
The monostate pattern is often presented as an alternative to a singleton based
|
||||
configuration system. This is exactly its purpose in `EnTT`. Moreover, this
|
||||
implementation is thread safe by design (hopefully).<br/>
|
||||
Keys are represented by hashed strings, values are basic types like `int`s or
|
||||
`bool`s. Values of different types can be associated to each key, even more than
|
||||
one at a time. Because of this, users must pay attention to use the same type
|
||||
both during an assignment and when they try to read back their data. Otherwise,
|
||||
they will probably incur in unexpected results.
|
||||
|
||||
Example of use:
|
||||
|
||||
```cpp
|
||||
entt::Monostate<entt::HashedString{"mykey"}>{} = true;
|
||||
entt::Monostate<"mykey"_hs>{} = 42;
|
||||
|
||||
// ...
|
||||
|
||||
const bool b = entt::Monostate<"mykey"_hs>{};
|
||||
const int i = entt::Monostate<entt::HashedString{"mykey"}>{};
|
||||
```
|
||||
|
||||
# Crash Course: service locator
|
||||
|
||||
Usually service locators are tightly bound to the services they expose and it's
|
||||
|
||||
1
TODO
1
TODO
@@ -7,7 +7,6 @@
|
||||
* define systems as composable mixins (initializazion, reactive, update, whatever) with flexible auto-detected arguments (registry, views, etc)
|
||||
* create dedicated flat map based on types implementation (sort of "type map") for types to use within the registry and so on...
|
||||
* ease the assignment of tags as string (type-less assign member function + user defined literal for hashed strings)
|
||||
* config system with atomic (something like Config<"foobar"_hs>::set(true) and Config<"foobar"_hs>::get<bool>())
|
||||
* work stealing job system (see #100)
|
||||
* C++17. That's all.
|
||||
* AOB
|
||||
|
||||
61
src/entt/core/monostate.hpp
Normal file
61
src/entt/core/monostate.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef ENTT_CORE_MONOSTATE_HPP
|
||||
#define ENTT_CORE_MONOSTATE_HPP
|
||||
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include "family.hpp"
|
||||
#include "hashed_string.hpp"
|
||||
|
||||
|
||||
namespace entt {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Minimal implementation of the monostate pattern.
|
||||
*
|
||||
* A minimal, yet complete configuration system built on top of the monostate
|
||||
* pattern. Thread safe by design, it works only with basic types like `int`s or
|
||||
* `bool`s.<br/>
|
||||
* Multiple types and therefore more than one value can be associated with a
|
||||
* single key. Because of this, users must pay attention to use the same type
|
||||
* both during an assignment and when they try to read back their data.
|
||||
* Otherwise, they can incur in unexpected results.
|
||||
*/
|
||||
template<HashedString::hash_type>
|
||||
struct Monostate {
|
||||
/**
|
||||
* @brief Assigns a value of a specific type to a given key.
|
||||
* @tparam Type Type of the value to assign.
|
||||
* @param val User data to assign to the given key.
|
||||
*/
|
||||
template<typename Type>
|
||||
void operator=(Type val) const ENTT_NOEXCEPT {
|
||||
Monostate::value<Type> = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value of a specific type for a given key.
|
||||
* @tparam Type Type of the value to get.
|
||||
* @return Stored value, if any.
|
||||
*/
|
||||
template<typename Type>
|
||||
operator Type() const ENTT_NOEXCEPT {
|
||||
return Monostate::value<Type>;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Type>
|
||||
static std::atomic<Type> value;
|
||||
};
|
||||
|
||||
|
||||
template<HashedString::hash_type ID>
|
||||
template<typename Type>
|
||||
std::atomic<Type> Monostate<ID>::value{};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // ENTT_CORE_MONOSTATE_HPP
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "core/family.hpp"
|
||||
#include "core/hashed_string.hpp"
|
||||
#include "core/ident.hpp"
|
||||
#include "core/monostate.hpp"
|
||||
#include "entity/actor.hpp"
|
||||
#include "entity/entity.hpp"
|
||||
#include "entity/entt_traits.hpp"
|
||||
|
||||
@@ -70,6 +70,7 @@ ADD_ENTT_TEST(algorithm entt/core/algorithm.cpp)
|
||||
ADD_ENTT_TEST(family entt/core/family.cpp)
|
||||
ADD_ENTT_TEST(hashed_string entt/core/hashed_string.cpp)
|
||||
ADD_ENTT_TEST(ident entt/core/ident.cpp)
|
||||
ADD_ENTT_TEST(monostate entt/core/monostate.cpp)
|
||||
|
||||
# Test entity
|
||||
|
||||
|
||||
20
test/entt/core/monostate.cpp
Normal file
20
test/entt/core/monostate.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/core/monostate.hpp>
|
||||
|
||||
TEST(Monostate, Functionalities) {
|
||||
const bool bPre = entt::Monostate<entt::HashedString{"foobar"}>{};
|
||||
const int iPre = entt::Monostate<"foobar"_hs>{};
|
||||
|
||||
ASSERT_FALSE(bPre);
|
||||
ASSERT_EQ(iPre, int{});
|
||||
|
||||
entt::Monostate<"foobar"_hs>{} = true;
|
||||
entt::Monostate<"foobar"_hs>{} = 42;
|
||||
|
||||
const bool &bPost = entt::Monostate<"foobar"_hs>{};
|
||||
const int &iPost = entt::Monostate<entt::HashedString{"foobar"}>{};
|
||||
|
||||
ASSERT_TRUE(bPost);
|
||||
ASSERT_EQ(iPost, 42);
|
||||
}
|
||||
Reference in New Issue
Block a user