mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-21 18:17:03 +08:00
fix: add thread safety for cave and river path mutexes
This commit is contained in:
@@ -17,11 +17,13 @@ public:
|
|||||||
|
|
||||||
int cave_sum() const;
|
int cave_sum() const;
|
||||||
float& cave_probability();
|
float& cave_probability();
|
||||||
|
std::shared_mutex& path_mutex();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CaveHashMap m_paths;
|
CaveHashMap m_paths;
|
||||||
unsigned m_seed = 0;
|
unsigned m_seed = 0;
|
||||||
Random m_random;
|
Random m_random;
|
||||||
float m_cave_probability = 0.035f;
|
float m_cave_probability = 0.035f;
|
||||||
|
std::shared_mutex m_path_mutex;
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class RiverWorm {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
RiverWorm();
|
RiverWorm();
|
||||||
|
~RiverWorm();
|
||||||
RiverHashMap& paths();
|
RiverHashMap& paths();
|
||||||
void init(unsigned world_seed);
|
void init(unsigned world_seed);
|
||||||
void reload(unsigned world_seed);
|
void reload(unsigned world_seed);
|
||||||
@@ -21,12 +22,14 @@ public:
|
|||||||
|
|
||||||
int river_sum() const;
|
int river_sum() const;
|
||||||
float& river_probability();
|
float& river_probability();
|
||||||
|
std::shared_mutex& paths_mutex();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RiverHashMap m_paths;
|
RiverHashMap m_paths;
|
||||||
unsigned m_seed = 0;
|
unsigned m_seed = 0;
|
||||||
Random m_random;
|
Random m_random;
|
||||||
float m_probability = 0.01f;
|
float m_probability = 0.01f;
|
||||||
|
std::shared_mutex m_paths_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace Cubed
|
}; // namespace Cubed
|
||||||
@@ -104,6 +104,7 @@ private:
|
|||||||
|
|
||||||
void submit_new_chunks();
|
void submit_new_chunks();
|
||||||
void poll_finished_chunks();
|
void poll_finished_chunks();
|
||||||
|
void wait_all_chunk_tasks();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
World();
|
World();
|
||||||
|
|||||||
@@ -48,7 +48,14 @@ public:
|
|||||||
for (auto& w : m_workers) {
|
for (auto& w : m_workers) {
|
||||||
w.request_stop();
|
w.request_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cv.notify_all();
|
m_cv.notify_all();
|
||||||
|
|
||||||
|
for (auto& w : m_workers) {
|
||||||
|
if (w.joinable()) {
|
||||||
|
w.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
template <typename F> auto enqueue(F&& f) {
|
template <typename F> auto enqueue(F&& f) {
|
||||||
|
|
||||||
|
|||||||
@@ -63,5 +63,5 @@ void CaveCarver::cleanup_finished_caves() {
|
|||||||
|
|
||||||
int CaveCarver::cave_sum() const { return m_paths.size(); }
|
int CaveCarver::cave_sum() const { return m_paths.size(); }
|
||||||
float& CaveCarver::cave_probability() { return m_cave_probability; }
|
float& CaveCarver::cave_probability() { return m_cave_probability; }
|
||||||
|
std::shared_mutex& CaveCarver::path_mutex() { return m_path_mutex; }
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -723,14 +723,17 @@ void ChunkGenerator::generate_cave() {
|
|||||||
auto& paths = cave_carver.paths();
|
auto& paths = cave_carver.paths();
|
||||||
const auto& chunk_pos = m_chunk.chunk_pos();
|
const auto& chunk_pos = m_chunk.chunk_pos();
|
||||||
auto& blocks = m_chunk.blocks();
|
auto& blocks = m_chunk.blocks();
|
||||||
|
{
|
||||||
|
std::shared_lock lock(cave_carver.path_mutex());
|
||||||
for (auto& [id, path] : paths) {
|
for (auto& [id, path] : paths) {
|
||||||
|
|
||||||
carve_worm(path.points(), chunk_pos, [&](int x, int y, int z) -> void {
|
carve_worm(path.points(), chunk_pos,
|
||||||
|
[&](int x, int y, int z) -> void {
|
||||||
int idx = Chunk::index(x, y, z);
|
int idx = Chunk::index(x, y, z);
|
||||||
if (blocks[idx] == 7)
|
if (blocks[idx] == 7)
|
||||||
return;
|
return;
|
||||||
if (y < WORLD_SIZE_Y - 1 && blocks[Chunk::index(x, y + 1, z)] == 7)
|
if (y < WORLD_SIZE_Y - 1 &&
|
||||||
|
blocks[Chunk::index(x, y + 1, z)] == 7)
|
||||||
return;
|
return;
|
||||||
blocks[idx] = 0;
|
blocks[idx] = 0;
|
||||||
});
|
});
|
||||||
@@ -738,6 +741,7 @@ void ChunkGenerator::generate_cave() {
|
|||||||
path.clear_chunk(chunk_pos);
|
path.clear_chunk(chunk_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChunkGenerator::generate_river() {
|
void ChunkGenerator::generate_river() {
|
||||||
@@ -746,16 +750,19 @@ void ChunkGenerator::generate_river() {
|
|||||||
auto& paths = river_worm.paths();
|
auto& paths = river_worm.paths();
|
||||||
const auto& chunk_pos = m_chunk.chunk_pos();
|
const auto& chunk_pos = m_chunk.chunk_pos();
|
||||||
auto& blocks = m_chunk.blocks();
|
auto& blocks = m_chunk.blocks();
|
||||||
|
|
||||||
bool is_river = false;
|
bool is_river = false;
|
||||||
|
{
|
||||||
|
std::shared_lock lock(river_worm.paths_mutex());
|
||||||
for (auto& [id, path] : paths) {
|
for (auto& [id, path] : paths) {
|
||||||
if ((m_chunk.biome() == BiomeType::DESERT) ||
|
if ((m_chunk.biome() == BiomeType::DESERT) ||
|
||||||
(m_chunk.biome() == BiomeType::OCEAN)) {
|
(m_chunk.biome() == BiomeType::OCEAN)) {
|
||||||
|
if (!m_chunk.is_temp_chunk()) {
|
||||||
path.clear_chunk(chunk_pos);
|
path.clear_chunk(chunk_pos);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
carve_worm(path.points(), chunk_pos, [&](int x, int y, int z) -> void {
|
carve_worm(path.points(), chunk_pos,
|
||||||
|
[&](int x, int y, int z) -> void {
|
||||||
int idx = Chunk::index(x, y, z);
|
int idx = Chunk::index(x, y, z);
|
||||||
if (y > SEA_LEVEL) {
|
if (y > SEA_LEVEL) {
|
||||||
blocks[idx] = 0;
|
blocks[idx] = 0;
|
||||||
@@ -771,6 +778,7 @@ void ChunkGenerator::generate_river() {
|
|||||||
path.clear_chunk(chunk_pos);
|
path.clear_chunk(chunk_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (is_river) {
|
if (is_river) {
|
||||||
m_chunk.biome(RIVER);
|
m_chunk.biome(RIVER);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
RiverWorm::RiverWorm() {}
|
RiverWorm::RiverWorm() {}
|
||||||
|
RiverWorm::~RiverWorm() {}
|
||||||
RiverWorm::RiverHashMap& RiverWorm::paths() { return m_paths; }
|
RiverWorm::RiverHashMap& RiverWorm::paths() { return m_paths; }
|
||||||
|
|
||||||
void RiverWorm::init(unsigned world_seed) {
|
void RiverWorm::init(unsigned world_seed) {
|
||||||
@@ -60,5 +60,6 @@ void RiverWorm::cleanup_finished_rivers() {
|
|||||||
|
|
||||||
int RiverWorm::river_sum() const { return m_paths.size(); }
|
int RiverWorm::river_sum() const { return m_paths.size(); }
|
||||||
float& RiverWorm::river_probability() { return m_probability; }
|
float& RiverWorm::river_probability() { return m_probability; }
|
||||||
|
std::shared_mutex& RiverWorm::paths_mutex() { return m_paths_mutex; }
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -21,6 +21,9 @@ World::World() {}
|
|||||||
World::~World() {
|
World::~World() {
|
||||||
stop_gen_thread();
|
stop_gen_thread();
|
||||||
stop_server_thread();
|
stop_server_thread();
|
||||||
|
wait_all_chunk_tasks();
|
||||||
|
m_gen_thread_pool.reset();
|
||||||
|
|
||||||
m_chunks.clear();
|
m_chunks.clear();
|
||||||
{
|
{
|
||||||
std::lock_guard lk(m_delete_vbo_mutex);
|
std::lock_guard lk(m_delete_vbo_mutex);
|
||||||
@@ -38,6 +41,12 @@ World::~World() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::wait_all_chunk_tasks() {
|
||||||
|
for (auto& [pos, task] : new_chunks) {
|
||||||
|
task.future.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool World::can_move(const AABB& player_box) const { return true; }
|
bool World::can_move(const AABB& player_box) const { return true; }
|
||||||
|
|
||||||
const std::optional<LookBlock>&
|
const std::optional<LookBlock>&
|
||||||
@@ -158,21 +167,26 @@ void World::gen_chunks_internal() {
|
|||||||
new_chunks.emplace(pos, Chunk(*this, pos));
|
new_chunks.emplace(pos, Chunk(*this, pos));
|
||||||
}
|
}
|
||||||
auto t1 = system_clock::now();
|
auto t1 = system_clock::now();
|
||||||
parallel_do(*m_gen_thread_pool, temp_neighbor.begin(), temp_neighbor.end(),
|
{
|
||||||
m_gen_thread_pool->thread_sum(),
|
std::scoped_lock lock{m_cave_carcer.path_mutex(),
|
||||||
|
m_river_worm.paths_mutex()};
|
||||||
|
parallel_do(*m_gen_thread_pool, temp_neighbor.begin(),
|
||||||
|
temp_neighbor.end(), m_gen_thread_pool->thread_sum(),
|
||||||
[this](std::pair<ChunkPos, Chunk>& new_chunk) {
|
[this](std::pair<ChunkPos, Chunk>& new_chunk) {
|
||||||
auto& [pos, chunk] = new_chunk;
|
auto& [pos, chunk] = new_chunk;
|
||||||
chunk.gen_phase_one();
|
chunk.gen_phase_one();
|
||||||
m_cave_carcer.try_to_add_path(pos, chunk.seed());
|
m_cave_carcer.try_to_add_path(pos, chunk.seed());
|
||||||
m_river_worm.try_to_add_path(pos, chunk.seed());
|
m_river_worm.try_to_add_path(pos, chunk.seed());
|
||||||
});
|
});
|
||||||
|
m_cave_carcer.cleanup_finished_caves();
|
||||||
|
m_river_worm.cleanup_finished_rivers();
|
||||||
|
}
|
||||||
|
|
||||||
auto t2 = system_clock::now();
|
auto t2 = system_clock::now();
|
||||||
Logger::info("Temp Neighbor Add Path Consum {}",
|
Logger::info("Temp Neighbor Add Path Consum {}",
|
||||||
duration_cast<milliseconds>(t2 - t1));
|
duration_cast<milliseconds>(t2 - t1));
|
||||||
m_chunk_gen_fraction = 0.9f;
|
m_chunk_gen_fraction = 0.9f;
|
||||||
|
|
||||||
m_cave_carcer.cleanup_finished_caves();
|
|
||||||
m_river_worm.cleanup_finished_rivers();
|
|
||||||
m_chunk_gen_fraction = 1.0f;
|
m_chunk_gen_fraction = 1.0f;
|
||||||
submit_new_chunks();
|
submit_new_chunks();
|
||||||
m_chunk_gen_finished = true;
|
m_chunk_gen_finished = true;
|
||||||
@@ -209,10 +223,6 @@ void World::compute_required_chunks(ChunkPosSet& required_chunks,
|
|||||||
for (int dz = -radius; dz <= radius; ++dz) {
|
for (int dz = -radius; dz <= radius; ++dz) {
|
||||||
if (dx * dx + dz * dz <= r2) {
|
if (dx * dx + dz * dz <= r2) {
|
||||||
ChunkPos pos{chunk_x + dx, chunk_z + dz};
|
ChunkPos pos{chunk_x + dx, chunk_z + dz};
|
||||||
auto it = required_chunks.find(pos);
|
|
||||||
if (it != required_chunks.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
temp_neighbor.emplace_back(pos, Chunk(*this, pos));
|
temp_neighbor.emplace_back(pos, Chunk(*this, pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user