diff --git a/include/Cubed/constants.hpp b/include/Cubed/constants.hpp index a8a3151..aad82aa 100644 --- a/include/Cubed/constants.hpp +++ b/include/Cubed/constants.hpp @@ -26,7 +26,7 @@ constexpr float DEFAULT_G = 22.5f; constexpr int SIZE_X = CHUNK_SIZE; constexpr int SIZE_Y = WORLD_SIZE_Y; constexpr int SIZE_Z = CHUNK_SIZE; - +constexpr int RESERVED_THREADS = 3; constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {-1, 1}, {1, -1}, {-1, -1}}; diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp index 38a0f64..5be6032 100644 --- a/include/Cubed/gameplay/world.hpp +++ b/include/Cubed/gameplay/world.hpp @@ -58,7 +58,7 @@ private: std::thread m_gen_thread; std::thread m_server_thread; - std::unique_ptr m_gen_thread_pool; + std::atomic> m_gen_thread_pool; std::stop_source m_server_stop_source; std::atomic m_per_tick_time = DEFAULT_PER_TICK_TIME; // ms @@ -159,6 +159,8 @@ public: bool is_tick_running() const; void tick_running(bool run); + + void change_pool_threads(int threads); }; } // namespace Cubed diff --git a/include/Cubed/tools/thread_pool.hpp b/include/Cubed/tools/thread_pool.hpp index 49a3184..5b53eaa 100644 --- a/include/Cubed/tools/thread_pool.hpp +++ b/include/Cubed/tools/thread_pool.hpp @@ -43,20 +43,7 @@ public: }); } } - ~ThreadPool() { - m_stopping = true; - for (auto& w : m_workers) { - w.request_stop(); - } - - m_cv.notify_all(); - - for (auto& w : m_workers) { - if (w.joinable()) { - w.join(); - } - } - } + ~ThreadPool() { stop(); } template auto enqueue(F&& f) { using R = std::invoke_result_t; @@ -74,6 +61,20 @@ public: m_cv.notify_one(); return fut; } + void stop() { + m_stopping = true; + for (auto& w : m_workers) { + w.request_stop(); + } + + m_cv.notify_all(); + + for (auto& w : m_workers) { + if (w.joinable()) { + w.join(); + } + } + } size_t thread_sum() const { return m_thread_sum.load(); } }; diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp index a1028ed..62321d7 100644 --- a/src/gameplay/world.cpp +++ b/src/gameplay/world.cpp @@ -22,7 +22,11 @@ World::~World() { stop_gen_thread(); stop_server_thread(); wait_all_chunk_tasks(); - m_gen_thread_pool.reset(); + auto pool_ptr = m_gen_thread_pool.load(); + if (pool_ptr) { + pool_ptr->stop(); + } + m_gen_thread_pool.store(nullptr); m_chunks.clear(); { @@ -86,10 +90,7 @@ void World::init_world() { m_river_worm.init(ChunkGenerator::seed()); m_chunks.reserve(MAX_DISTANCE * MAX_DISTANCE * 4); int max_thread = std::thread::hardware_concurrency(); - int used_thread = std::max(max_thread - 3, 1); - Logger::info("Max Support Thread is {}, use {} threads to gen", max_thread, - used_thread); - m_gen_thread_pool = std::make_unique(used_thread); + change_pool_threads(max_thread - RESERVED_THREADS); auto t1 = std::chrono::system_clock::now(); @@ -170,8 +171,12 @@ void World::gen_chunks_internal() { { 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(), + auto pool_ptr = m_gen_thread_pool.load(); + if (!pool_ptr) { + return; + } + parallel_do(*pool_ptr, temp_neighbor.begin(), temp_neighbor.end(), + pool_ptr->thread_sum(), [this](std::pair& new_chunk) { auto& [pos, chunk] = new_chunk; chunk.gen_phase_one(); @@ -251,10 +256,14 @@ void World::sync_and_collect_missing_chunks( void World::submit_new_chunks() { std::lock_guard lock(m_new_chunk_mutex); + auto pool_ptr = m_gen_thread_pool.load(); + if (!pool_ptr) { + return; + } for (auto& [pos, task] : new_chunks) { if (!task.future.valid()) { - task.future = m_gen_thread_pool->enqueue( - [&task]() { task.chunk.gen_chunk(); }); + task.future = + pool_ptr->enqueue([&task]() { task.chunk.gen_chunk(); }); } } } @@ -648,4 +657,13 @@ void World::per_tick_time(int ms) { m_per_tick_time = ms; } bool World::is_tick_running() const { return m_tick_running.load(); } void World::tick_running(bool run) { m_tick_running = run; } +void World::change_pool_threads(int threads) { + int max_thread = std::thread::hardware_concurrency(); + if (max_thread < 1) { + max_thread = 4; + } + int used_thread = std::clamp(threads, 1, max_thread); + Logger::info("Create New Thread Pool Use {} Threads", used_thread); + m_gen_thread_pool.store(std::make_shared(used_thread)); +} } // namespace Cubed \ No newline at end of file