summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-10-17 11:35:46 +0200
committerStanislaw Halik <sthalik@misaki.pl>2022-10-17 11:35:46 +0200
commit5c3bcde8f859b08275fa09f32800360ee541d5bd (patch)
treed428f3d1facbb433d787c25d55f20b11ac92aadd
parent66f89e04a50ad6ed8448c20c1731a3750d08e624 (diff)
a
-rw-r--r--compat/assert.hpp16
-rw-r--r--compat/defs.hpp2
-rw-r--r--compat/int-hash.hpp30
-rw-r--r--src/global-coords.hpp1
-rw-r--r--src/world.cpp40
-rw-r--r--src/world.hpp22
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