diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-10-17 11:35:46 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-10-17 11:35:46 +0200 |
commit | 5c3bcde8f859b08275fa09f32800360ee541d5bd (patch) | |
tree | d428f3d1facbb433d787c25d55f20b11ac92aadd | |
parent | 66f89e04a50ad6ed8448c20c1731a3750d08e624 (diff) |
a
-rw-r--r-- | compat/assert.hpp | 16 | ||||
-rw-r--r-- | compat/defs.hpp | 2 | ||||
-rw-r--r-- | compat/int-hash.hpp | 30 | ||||
-rw-r--r-- | src/global-coords.hpp | 1 | ||||
-rw-r--r-- | src/world.cpp | 40 | ||||
-rw-r--r-- | src/world.hpp | 22 |
6 files changed, 75 insertions, 36 deletions
diff --git a/compat/assert.hpp b/compat/assert.hpp index 860a9cde..04c5acbe 100644 --- a/compat/assert.hpp +++ b/compat/assert.hpp @@ -59,3 +59,19 @@ constexpr inline void abort(const char (&fmt)[N], Xs... xs) noexcept #define ERR(...) ::floormat::detail::emit_debug("error: ", __VA_ARGS__) #define MESSAGE(...) ::floormat::detail::emit_debug("", __VA_ARGS__) #define DEBUG(...) ::floormat::detail::emit_debug("", __VA_ARGS__) + +namespace floormat { + +template<bool> +struct static_warning_ final { + [[deprecated]] constexpr static_warning_() = default; +}; + +template<> +struct static_warning_<true> final { + constexpr static_warning_() = default; +}; + +#define static_warning(...) do { (void)static_warning_<(__VA_ARGS__)>{}; } while(false) + +} // namespace floormat diff --git a/compat/defs.hpp b/compat/defs.hpp index 818e004b..632bafe5 100644 --- a/compat/defs.hpp +++ b/compat/defs.hpp @@ -15,3 +15,5 @@ #define DECLARE_DELETED_COPY_ASSIGNMENT(type) \ type(const type&) = delete; \ type& operator=(const type&) = delete + + diff --git a/compat/int-hash.hpp b/compat/int-hash.hpp new file mode 100644 index 00000000..43b92605 --- /dev/null +++ b/compat/int-hash.hpp @@ -0,0 +1,30 @@ +#pragma once +#include <cstddef> + +namespace floormat { + +constexpr inline std::size_t int_hash(std::size_t x) noexcept +{ + if constexpr(sizeof(std::size_t) == 4) + { + // by Chris Wellons <https://nullprogram.com/blog/2018/07/31/> + x ^= x >> 15; + x *= 0x2c1b3c6dU; + x ^= x >> 12; + x *= 0x297a2d39U; + x ^= x >> 15; + } + else if constexpr(sizeof(std::size_t) == 8) + { + // splitmix64 by George Marsaglia + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9U; + x ^= x >> 27; + x *= 0x94d049bb133111ebU; + x ^= x >> 31; + } + + return x; +} + +} // namespace floormat diff --git a/src/global-coords.hpp b/src/global-coords.hpp index 284c63c5..e51dc6aa 100644 --- a/src/global-coords.hpp +++ b/src/global-coords.hpp @@ -8,7 +8,6 @@ struct chunk_coords final { std::int16_t x = 0, y = 0; constexpr bool operator==(const chunk_coords& other) const noexcept = default; - constexpr operator std::size_t() const noexcept { return (std::uint32_t)y << 16 | (std::uint32_t)x; } }; struct global_coords final { diff --git a/src/world.cpp b/src/world.cpp index 5018b5c9..3057fca8 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -16,10 +16,11 @@ world::world() std::shared_ptr<chunk> world::operator[](chunk_coords c) noexcept { auto [it, inserted] = _chunks.try_emplace(c, chunk_pointer_maker{}); - maybe_collect(); return it->second; + const auto ret = it->second; + return maybe_collect(), ret; } -std::shared_ptr<const chunk> world::maybe_chunk(chunk_coords c) const noexcept +std::shared_ptr<chunk> world::maybe_chunk(chunk_coords c) noexcept { if (const auto it = _chunks.find(c); it != _chunks.cend()) return it->second; @@ -27,9 +28,9 @@ std::shared_ptr<const chunk> world::maybe_chunk(chunk_coords c) const noexcept return nullptr; } -std::shared_ptr<chunk> world::maybe_chunk(chunk_coords c) noexcept +std::shared_ptr<const chunk> world::maybe_chunk(chunk_coords c) const noexcept { - return std::const_pointer_cast<chunk>(const_cast<const world&>(*this).maybe_chunk(c)); + return const_cast<world&>(*this).maybe_chunk(c); } bool world::contains(chunk_coords c) const noexcept @@ -40,6 +41,7 @@ bool world::contains(chunk_coords c) const noexcept void world::clear() { _last_collection = 0; + _chunks.clear(); _chunks.rehash(initial_capacity); } @@ -53,39 +55,13 @@ void world::collect() { for (auto it = _chunks.begin(); it != _chunks.end(); (void)0) { - const auto& [k, c] = *it; + const auto& [_, c] = *it; if (c->empty()) it = _chunks.erase(it); else - it++; + ++it; } _last_collection = _chunks.size(); } -std::size_t world::hasher::operator()(chunk_coords c) const noexcept -{ - std::size_t x = (std::size_t)c.y << 16 | (std::size_t)c.x; - - if constexpr(sizeof(std::size_t) == 4) - { - // by Chris Wellons <https://nullprogram.com/blog/2018/07/31/> - x ^= x >> 15; - x *= 0x2c1b3c6dU; - x ^= x >> 12; - x *= 0x297a2d39U; - x ^= x >> 15; - } - else if constexpr(sizeof(std::size_t) == 8) - { - // splitmix64 by George Marsaglia - x ^= x >> 30; - x *= 0xbf58476d1ce4e5b9U; - x ^= x >> 27; - x *= 0x94d049bb133111ebU; - x ^= x >> 31; - } - - return x; -} - } // namespace floormat diff --git a/src/world.hpp b/src/world.hpp index 75e05bd8..1e8469d9 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -1,8 +1,25 @@ #pragma once +#include "compat/int-hash.hpp" #include "global-coords.hpp" #include <unordered_map> #include <memory> +namespace std { + +template<typename> struct hash; + +template<> +struct hash<floormat::chunk_coords> final +{ + constexpr + std::size_t operator()(floormat::chunk_coords c) const noexcept + { + return floormat::int_hash((std::size_t)c.y << 16 | (std::size_t)c.x); + } +}; + +} // namespace std + namespace floormat { struct chunk; @@ -18,14 +35,13 @@ struct world final void collect(); private: - static constexpr std::size_t initial_capacity = 64, collect_every = 100; + static constexpr std::size_t initial_capacity = 64, collect_every = 32; static constexpr float max_load_factor = .5; std::size_t _last_collection = 0; void maybe_collect(); - struct hasher final { std::size_t operator()(chunk_coords c) const noexcept; }; - std::unordered_map<chunk_coords, std::shared_ptr<chunk>, hasher> _chunks{initial_capacity}; + std::unordered_map<chunk_coords, std::shared_ptr<chunk>> _chunks{initial_capacity}; }; } // namespace floormat |