mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-21 18:17:03 +08:00
feat(world): add dynamic thread pool resizing
This commit is contained in:
@@ -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}};
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ private:
|
||||
|
||||
std::thread m_gen_thread;
|
||||
std::thread m_server_thread;
|
||||
std::unique_ptr<ThreadPool> m_gen_thread_pool;
|
||||
std::atomic<std::shared_ptr<ThreadPool>> m_gen_thread_pool;
|
||||
std::stop_source m_server_stop_source;
|
||||
|
||||
std::atomic<int> 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
|
||||
|
||||
@@ -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 <typename F> auto enqueue(F&& f) {
|
||||
|
||||
using R = std::invoke_result_t<F>;
|
||||
@@ -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(); }
|
||||
};
|
||||
|
||||
|
||||
@@ -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<ThreadPool>(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<ChunkPos, Chunk>& 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<ThreadPool>(used_thread));
|
||||
}
|
||||
} // namespace Cubed
|
||||
Reference in New Issue
Block a user