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:
Jérémy Rosen 2007-02-02 22:09:12 +00:00
parent 9d5607271d
commit 3f7f8c366b
7 changed files with 37 additions and 22 deletions

View file

@ -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

View file

@ -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");

View file

@ -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()

View file

@ -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:

View file

@ -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;
}

View file

@ -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:

View file

@ -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;