allow an easy way to fix an upper limit to the number of threads used,
...limit is 1 for client and unlimited for wesnothd and campaignd. limits for the servers can be set via CLI
This commit is contained in:
parent
9d5607271d
commit
3f7f8c366b
7 changed files with 37 additions and 22 deletions
|
@ -217,7 +217,8 @@ Version 1.3-svn:
|
|||
* better handling of SDL_ListModes return code (no user impact)
|
||||
* first turn of a game is saved again (fixes bug #7909 and bug #8117)
|
||||
* reduce CPU usage by removing calls to SDL_GetTicks for idle animations
|
||||
* changed network thread management to be more scalable
|
||||
* changed network thread management to be more scalable, both with an upper
|
||||
and lower number of threads
|
||||
* enabled python as default, to disable it use --disable-python
|
||||
* various code cleanups
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace {
|
|||
class campaign_server
|
||||
{
|
||||
public:
|
||||
explicit campaign_server(const std::string& cfgfile,unsigned int nthread = 10);
|
||||
explicit campaign_server(const std::string& cfgfile,size_t min_thread = 10,size_t max_thread = 0);
|
||||
void run();
|
||||
private:
|
||||
int load_config(); // return the server port
|
||||
|
@ -66,8 +66,8 @@ namespace {
|
|||
return lexical_cast_default<int>(cfg_["port"], 15003);
|
||||
}
|
||||
|
||||
campaign_server::campaign_server(const std::string& cfgfile,unsigned int nthread)
|
||||
: file_(cfgfile), net_manager_(nthread), server_manager_(load_config())
|
||||
campaign_server::campaign_server(const std::string& cfgfile,size_t min_thread,size_t max_thread)
|
||||
: file_(cfgfile), net_manager_(min_thread,max_thread), server_manager_(load_config())
|
||||
{
|
||||
if(cfg_.child("campaigns") == NULL) {
|
||||
cfg_.add_child("campaigns");
|
||||
|
|
|
@ -183,7 +183,7 @@ void error::disconnect()
|
|||
network::disconnect(socket);
|
||||
}
|
||||
|
||||
manager::manager(size_t nthreads) : free_(true)
|
||||
manager::manager(size_t min_threads, size_t max_threads) : free_(true)
|
||||
{
|
||||
//if the network is already being managed
|
||||
if(socket_set) {
|
||||
|
@ -204,7 +204,7 @@ manager::manager(size_t nthreads) : free_(true)
|
|||
|
||||
socket_set = SDLNet_AllocSocketSet(512);
|
||||
|
||||
worker_pool_man = new network_worker_pool::manager(nthreads);
|
||||
worker_pool_man = new network_worker_pool::manager(min_threads, max_threads);
|
||||
}
|
||||
|
||||
manager::~manager()
|
||||
|
|
|
@ -31,8 +31,14 @@ namespace network {
|
|||
|
||||
//a network manager must be created before networking can be used.
|
||||
//it must be destroyed only after all networking activity stops.
|
||||
|
||||
// min_threads is the maximum number we allow to wait, of more threads attempt to wait, they will die
|
||||
// if min_threads == 0 no thread will ever be destroyed, and we will stay at the max number of threads ever needed
|
||||
|
||||
// max_threads is the overall max number of helper threads. if we have that many threads already running, we will never create more
|
||||
// if max_threads == 0 we will alway create a thread if we need it
|
||||
struct manager {
|
||||
explicit manager(size_t nthreads=2);
|
||||
explicit manager(size_t min_threads = 1,size_t max_threads = 0);
|
||||
~manager();
|
||||
|
||||
private:
|
||||
|
|
|
@ -80,7 +80,8 @@ struct _TCPsocket {
|
|||
};
|
||||
unsigned int buf_id = 0;
|
||||
unsigned int waiting_threads = 0;
|
||||
unsigned int thread_pool = 0;
|
||||
size_t min_threads = 0;
|
||||
size_t max_threads = 0;
|
||||
|
||||
struct buffer {
|
||||
explicit buffer(TCPsocket sock) : sock(sock) {}
|
||||
|
@ -302,7 +303,7 @@ int process_queue(void*)
|
|||
delete zombie;
|
||||
|
||||
}
|
||||
if(waiting_threads >= thread_pool) {
|
||||
if(min_threads && waiting_threads >= min_threads) {
|
||||
LOG_NW << "worker thread exiting... not enough job\n";
|
||||
to_clear.push_back(threading::get_current_thread_id());
|
||||
return 0;
|
||||
|
@ -354,8 +355,11 @@ int process_queue(void*)
|
|||
waiting_threads--;
|
||||
// if we are the last thread in the pool, create a new one
|
||||
if(!waiting_threads && managed == true) {
|
||||
threading::thread * tmp = new threading::thread(process_queue,NULL);
|
||||
threads[tmp->get_id()] =tmp;
|
||||
// max_threads of 0 is unlimited
|
||||
if(!max_threads || max_threads >threads.size()) {
|
||||
threading::thread * tmp = new threading::thread(process_queue,NULL);
|
||||
threads[tmp->get_id()] =tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,15 +402,16 @@ int process_queue(void*)
|
|||
namespace network_worker_pool
|
||||
{
|
||||
|
||||
manager::manager(size_t nthreads) : active_(!managed)
|
||||
manager::manager(size_t p_min_threads,size_t p_max_threads) : active_(!managed)
|
||||
{
|
||||
if(active_) {
|
||||
managed = true;
|
||||
global_mutex = new threading::mutex();
|
||||
cond = new threading::condition();
|
||||
thread_pool = nthreads;
|
||||
min_threads = p_min_threads;
|
||||
max_threads = p_max_threads;
|
||||
|
||||
for(size_t n = 0; n != nthreads; ++n) {
|
||||
for(size_t n = 0; n != min_threads; ++n) {
|
||||
threading::thread * tmp = new threading::thread(process_queue,NULL);
|
||||
threads[tmp->get_id()] =tmp;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace network_worker_pool
|
|||
|
||||
struct manager
|
||||
{
|
||||
explicit manager(size_t nthreads=2);
|
||||
explicit manager(size_t min_threads,size_t max_threads);
|
||||
~manager();
|
||||
|
||||
private:
|
||||
|
|
|
@ -88,7 +88,7 @@ void truncate_message(t_string& str)
|
|||
class server
|
||||
{
|
||||
public:
|
||||
server(int port, input_stream& input, const config& cfg, size_t nthreads);
|
||||
server(int port, input_stream& input, const config& cfg, size_t min_threads,size_t max_threads);
|
||||
void run();
|
||||
private:
|
||||
void process_data(network::connection sock, config& data, config& gamelist);
|
||||
|
@ -152,7 +152,7 @@ private:
|
|||
std::string motd_;
|
||||
};
|
||||
|
||||
server::server(int port, input_stream& input, const config& cfg, size_t nthreads) : net_manager_(nthreads), server_(port),
|
||||
server::server(int port, input_stream& input, const config& cfg, size_t min_threads,size_t max_threads) : net_manager_(min_threads,max_threads), server_(port),
|
||||
not_logged_in_(players_), lobby_players_(players_), last_stats_(time(NULL)), input_(input), cfg_(cfg), admin_passwd_(cfg["passwd"]), motd_(cfg["motd"])
|
||||
{
|
||||
version_query_response_.add_child("version");
|
||||
|
@ -1343,7 +1343,8 @@ void server::delete_game(std::vector<game>::iterator i)
|
|||
int main(int argc, char** argv)
|
||||
{
|
||||
int port = 15000;
|
||||
size_t nthreads = 5;
|
||||
size_t min_threads = 5;
|
||||
size_t max_threads = 0;
|
||||
|
||||
config configuration;
|
||||
|
||||
|
@ -1407,10 +1408,12 @@ int main(int argc, char** argv)
|
|||
setsid();
|
||||
#endif
|
||||
} else if((val == "--threads" || val == "-t") && arg+1 != argc) {
|
||||
nthreads = atoi(argv[++arg]);
|
||||
if(nthreads > 30) {
|
||||
nthreads = 30;
|
||||
min_threads = atoi(argv[++arg]);
|
||||
if(min_threads > 30) {
|
||||
min_threads = 30;
|
||||
}
|
||||
} else if((val == "--max-threads" || val == "-T") && arg+1 != argc) {
|
||||
max_threads = atoi(argv[++arg]);
|
||||
} else if(val[0] == '-') {
|
||||
std::cerr << "unknown option: " << val << "\n";
|
||||
return 0;
|
||||
|
@ -1422,7 +1425,7 @@ int main(int argc, char** argv)
|
|||
input_stream input(fifo_path);
|
||||
|
||||
try {
|
||||
server(port,input,configuration,nthreads).run();
|
||||
server(port,input,configuration,min_threads,max_threads).run();
|
||||
} catch(network::error& e) {
|
||||
std::cerr << "caught network error while server was running. aborting.: " << e.message << "\n";
|
||||
return -1;
|
||||
|
|
Loading…
Add table
Reference in a new issue