mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat(gameplay): add run mode based thread pool config
Introduce RunMode enum and thread pool sizing helpers for client, server, and hybrid modes. Add compute pool to server world and pass mode through server/client initialization.
This commit is contained in:
@@ -32,7 +32,7 @@ public:
|
||||
ClientWorld(AudioEngine& auido, Config& config, WorldScene& scene);
|
||||
~ClientWorld();
|
||||
void init(std::string_view player_name,
|
||||
std::shared_ptr<NetworkClient> client);
|
||||
std::shared_ptr<NetworkClient> client, RunMode mode);
|
||||
void update(float dt);
|
||||
bool handle_event(const Event& e);
|
||||
const std::optional<LookBlock>& get_look_block_pos() const;
|
||||
@@ -132,6 +132,7 @@ private:
|
||||
|
||||
static constexpr int WORLD_EXIT_TIMEOUT = 200;
|
||||
static constexpr int MAX_UPLOAD_CHUNK_SUM = 16;
|
||||
std::atomic<RunMode> m_runmode = RunMode::HYBRID;
|
||||
ClientEntityManager m_entity_manager;
|
||||
ClientPlayerManager m_player_manager;
|
||||
ChunkHashMap m_chunks;
|
||||
|
||||
@@ -14,8 +14,7 @@ public:
|
||||
void stop();
|
||||
|
||||
// Run in another thread after initialization is complete
|
||||
void start_server(int port);
|
||||
void start_server();
|
||||
void start_server(int port, RunMode mode);
|
||||
int port() const;
|
||||
ServerWorld& server_world();
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
~ServerWorld();
|
||||
void stop();
|
||||
void handle_player_exit(const std::string& uuid);
|
||||
void init_world();
|
||||
void init_world(RunMode mode);
|
||||
void need_gen(std::string uuid);
|
||||
void update();
|
||||
void hot_reload();
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
|
||||
uint32_t get_chunk_ref_count(const glm::vec3& pos) const;
|
||||
ServerEntityManager& entity_manager();
|
||||
|
||||
std::shared_ptr<ThreadPool> get_compute_pool();
|
||||
int get_block(const glm::ivec3& block_pos) const override;
|
||||
bool is_solid(const glm::ivec3& block_pos) const override;
|
||||
bool can_pass_block(const glm::ivec3& block_pos) const override;
|
||||
@@ -142,6 +142,7 @@ private:
|
||||
using uuid_cacc = PlayerUUIDMap::const_accessor;
|
||||
|
||||
Config& m_config;
|
||||
std::atomic<RunMode> m_runmode{RunMode::HYBRID};
|
||||
ServerEntityManager m_entity_manager;
|
||||
// key = uuid
|
||||
PlayerHashMap m_players;
|
||||
@@ -163,8 +164,9 @@ private:
|
||||
std::atomic<bool> m_init{false};
|
||||
std::atomic<bool> m_stopped{false};
|
||||
std::atomic<int> m_rendering_distance{24};
|
||||
std::atomic<int> m_gen_pool_threads{0};
|
||||
std::atomic<int> m_net_pool_threads{0};
|
||||
std::atomic<int> m_gen_threads{0};
|
||||
std::atomic<int> m_net_threads{0};
|
||||
std::atomic<int> m_compute_threads{0};
|
||||
std::atomic<int> m_max_threads{1};
|
||||
std::atomic<size_t> m_player_sum{0};
|
||||
std::atomic<TickType> m_game_ticks{0};
|
||||
@@ -180,6 +182,7 @@ private:
|
||||
|
||||
std::atomic<std::shared_ptr<PriorityThreadPool>> m_gen_thread_pool;
|
||||
std::atomic<std::shared_ptr<ThreadPool>> m_net_thread_pool;
|
||||
std::atomic<std::shared_ptr<ThreadPool>> m_compute_thread_pool;
|
||||
|
||||
std::atomic<ChunkLoadStyle> m_chunk_load_style{ChunkLoadStyle::CENTER};
|
||||
|
||||
|
||||
@@ -26,4 +26,7 @@ public:
|
||||
glm::vec3{0.5f, 0.5f, 0.5f}};
|
||||
}
|
||||
};
|
||||
|
||||
enum class RunMode { CLIENT_ONLY, SERVER_ONLY, HYBRID };
|
||||
|
||||
} // namespace Cubed
|
||||
130
include/Cubed/tools/threas_utils.hpp
Normal file
130
include/Cubed/tools/threas_utils.hpp
Normal file
@@ -0,0 +1,130 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/world.hpp"
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
namespace Cubed {
|
||||
namespace Tools {
|
||||
|
||||
constexpr size_t SERVER_RESERVED_THREADS = 3; // tick + netio + gen scheduler
|
||||
constexpr size_t CLIENT_RESERVED_THREADS =
|
||||
3; // main/render + netio + system reserved
|
||||
|
||||
constexpr size_t safe_sub(size_t a, size_t b) { return a > b ? a - b : 0; }
|
||||
|
||||
inline size_t get_hardware_threads() {
|
||||
auto hc = std::thread::hardware_concurrency();
|
||||
return hc == 0 ? 4 : static_cast<size_t>(hc);
|
||||
}
|
||||
|
||||
inline size_t get_server_available_threads() {
|
||||
return std::max<size_t>(
|
||||
1, safe_sub(get_hardware_threads(), SERVER_RESERVED_THREADS));
|
||||
}
|
||||
|
||||
inline size_t get_client_available_threads() {
|
||||
return std::max<size_t>(
|
||||
1, safe_sub(get_hardware_threads(), CLIENT_RESERVED_THREADS));
|
||||
}
|
||||
|
||||
inline size_t get_client_threads(RunMode mode) {
|
||||
switch (mode) {
|
||||
case RunMode::SERVER_ONLY:
|
||||
ASSERT_MSG(false, "Server Only don't need client pool");
|
||||
return 1;
|
||||
case RunMode::CLIENT_ONLY: {
|
||||
auto available = get_client_available_threads();
|
||||
return std::clamp<size_t>(available, 1, 16);
|
||||
}
|
||||
|
||||
case RunMode::HYBRID: {
|
||||
auto available = get_client_available_threads();
|
||||
return std::clamp<size_t>(available / 2, 1, 4);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline size_t get_server_net_pool_threads(RunMode mode) {
|
||||
switch (mode) {
|
||||
|
||||
case RunMode::SERVER_ONLY: {
|
||||
auto available = get_server_available_threads();
|
||||
return std::clamp<size_t>(available / 4, 1,
|
||||
std::min<size_t>(4, available));
|
||||
}
|
||||
|
||||
case RunMode::CLIENT_ONLY:
|
||||
ASSERT_MSG(false, "Client Only don't need net pool");
|
||||
return 1;
|
||||
case RunMode::HYBRID: {
|
||||
auto available = get_server_available_threads();
|
||||
return std::clamp<size_t>(available / 8, 1,
|
||||
std::min<size_t>(4, available));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline size_t get_server_compute_treads(RunMode mode) {
|
||||
switch (mode) {
|
||||
case RunMode::HYBRID:
|
||||
case RunMode::SERVER_ONLY: {
|
||||
auto available = get_server_available_threads();
|
||||
|
||||
return std::clamp<size_t>(available / 4, 1,
|
||||
std::min<size_t>(4, available));
|
||||
}
|
||||
case RunMode::CLIENT_ONLY:
|
||||
ASSERT_MSG(false, "Client Only don't need update pool");
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline size_t get_server_gen_threads(RunMode mode) {
|
||||
switch (mode) {
|
||||
case RunMode::SERVER_ONLY: {
|
||||
auto available = get_server_available_threads();
|
||||
|
||||
auto net_pool = get_server_net_pool_threads(mode);
|
||||
|
||||
auto update_pool = get_server_compute_treads(mode);
|
||||
|
||||
size_t remain = available;
|
||||
|
||||
remain -= std::min(remain, net_pool);
|
||||
|
||||
remain -= std::min(remain, update_pool);
|
||||
|
||||
return std::max<size_t>(1, remain);
|
||||
}
|
||||
case RunMode::CLIENT_ONLY:
|
||||
ASSERT_MSG(false, "Client Only don't need gen pool");
|
||||
return 1;
|
||||
case RunMode::HYBRID: {
|
||||
auto available = get_server_available_threads();
|
||||
|
||||
auto net_pool = get_server_net_pool_threads(mode);
|
||||
|
||||
auto update_pool = get_server_compute_treads(mode);
|
||||
|
||||
auto client_pool = get_client_threads(mode);
|
||||
|
||||
size_t remain = available;
|
||||
|
||||
remain -= std::min(remain, net_pool);
|
||||
|
||||
remain -= std::min(remain, update_pool);
|
||||
|
||||
remain -= std::min(remain, client_pool);
|
||||
|
||||
return std::max<size_t>(1, remain);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace Tools
|
||||
} // namespace Cubed
|
||||
Reference in New Issue
Block a user