fixed threaded jobs

This commit is contained in:
Magnus Auvinen 2008-09-07 21:13:24 +00:00
parent 6a4e17ea85
commit 3b086d616a
9 changed files with 261 additions and 140 deletions

View file

@ -1289,31 +1289,37 @@ static void client_update()
client_serverbrowse_update();
}
static int client_getversion()
static void client_versionupdate()
{
NETADDR addr;
NETCHUNK packet;
static int state = 0;
static HOSTLOOKUP version_serveraddr;
mem_zero(&addr, sizeof(NETADDR));
mem_zero(&packet, sizeof(NETCHUNK));
if(net_host_lookup(config.cl_version_server, &addr, NETTYPE_IPV4))
if(state == 0)
{
dbg_msg("client/version", "could not find the address of %s, skipping version fetch", config.cl_version_server);
return -1;
engine_hostlookup(&version_serveraddr, config.cl_version_server);
state++;
}
else if(state == 1)
{
if(jobs_status(&version_serveraddr.job) == JOBSTATUS_DONE)
{
NETCHUNK packet;
mem_zero(&packet, sizeof(NETCHUNK));
version_serveraddr.addr.port = VERSIONSRV_PORT;
packet.client_id = -1;
packet.address = version_serveraddr.addr;
packet.data = VERSIONSRV_GETVERSION;
packet.data_size = sizeof(VERSIONSRV_GETVERSION);
packet.flags = NETSENDFLAG_CONNLESS;
netclient_send(net, &packet);
state++;
}
}
addr.port = VERSIONSRV_PORT;
packet.client_id = -1;
packet.address = addr;
packet.data = VERSIONSRV_GETVERSION;
packet.data_size = sizeof(VERSIONSRV_GETVERSION);
packet.flags = NETSENDFLAG_CONNLESS;
netclient_send(net, &packet);
return 0;
}
extern int editor_update_and_render();
@ -1336,7 +1342,7 @@ static void client_run()
return;
/* start refreshing addresses while we load */
mastersrv_refresh_addresses();
/* mastersrv_refresh_addresses(); */
/* init the editor */
editor_init();
@ -1363,9 +1369,6 @@ static void client_run()
config.cl_connect[0] = 0;
*/
/* fetch latest client-version from versionsrv */
client_getversion();
/* never start with the editor */
config.cl_editor = 0;
@ -1377,7 +1380,11 @@ static void client_run()
int64 frame_start_time = time_get();
frames++;
perf_start(&rootscope);
/* */
client_versionupdate();
/* update input */
{

View file

@ -49,6 +49,8 @@ static SERVERENTRY *first_req_server = 0; /* request list */
static SERVERENTRY *last_req_server = 0;
static int num_requests = 0;
static int need_refresh = 0;
static int num_sorted_servers = 0;
static int num_sorted_servers_capacity = 0;
static int num_servers = 0;
@ -488,13 +490,64 @@ void client_serverbrowse_refresh(int type)
dbg_msg("client", "broadcasting for servers");
}
else if(type == BROWSETYPE_INTERNET)
{
need_refresh = 1;
mastersrv_refresh_addresses();
}
else if(type == BROWSETYPE_FAVORITES)
{
int i;
for(i = 0; i < num_favorite_servers; i++)
client_serverbrowse_set(&favorite_servers[i], BROWSESET_FAV_ADD, -1, 0);
}
}
static void client_serverbrowse_request(SERVERENTRY *entry)
{
/*unsigned char buffer[sizeof(SERVERBROWSE_GETINFO)+1];*/
NETCHUNK p;
if(config.debug)
{
dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d",
entry->addr.ip[0], entry->addr.ip[1], entry->addr.ip[2],
entry->addr.ip[3], entry->addr.port);
}
/*mem_copy(buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;*/
p.client_id = -1;
p.address = entry->addr;
p.flags = NETSENDFLAG_CONNLESS;
/*p.data_size = sizeof(buffer);
p.data = buffer;
netclient_send(net, &p);*/
/* send old requtest style aswell */
p.data_size = sizeof(SERVERBROWSE_OLD_GETINFO);
p.data = SERVERBROWSE_OLD_GETINFO;
netclient_send(net, &p);
entry->request_time = time_get();
}
void client_serverbrowse_update()
{
int64 timeout = time_freq();
int64 now = time_get();
int count;
SERVERENTRY *entry, *next;
/* do server list requests */
if(need_refresh && !mastersrv_refreshing())
{
NETADDR addr;
NETCHUNK p;
int i;
/*net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server);*/
need_refresh = 0;
mem_zero(&p, sizeof(p));
p.client_id = -1;
p.flags = NETSENDFLAG_CONNLESS;
@ -514,50 +567,6 @@ void client_serverbrowse_refresh(int type)
if(config.debug)
dbg_msg("client", "requesting server list");
}
else if(type == BROWSETYPE_FAVORITES)
{
int i;
for(i = 0; i < num_favorite_servers; i++)
client_serverbrowse_set(&favorite_servers[i], BROWSESET_FAV_ADD, -1, 0);
}
}
static void client_serverbrowse_request(SERVERENTRY *entry)
{
unsigned char buffer[sizeof(SERVERBROWSE_GETINFO)+1];
NETCHUNK p;
if(config.debug)
{
dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d",
entry->addr.ip[0], entry->addr.ip[1], entry->addr.ip[2],
entry->addr.ip[3], entry->addr.port);
}
mem_copy(buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;
p.client_id = -1;
p.address = entry->addr;
p.flags = NETSENDFLAG_CONNLESS;
p.data_size = sizeof(buffer);
p.data = buffer;
netclient_send(net, &p);
/* send old requtest style aswell */
p.data_size = sizeof(SERVERBROWSE_OLD_GETINFO);
p.data = SERVERBROWSE_OLD_GETINFO;
netclient_send(net, &p);
entry->request_time = time_get();
}
void client_serverbrowse_update()
{
int64 timeout = time_freq();
int64 now = time_get();
int count;
SERVERENTRY *entry, *next;
/* do timeouts */
entry = first_req_server;
@ -660,3 +669,9 @@ void client_serverbrowse_save()
engine_config_write_line(buffer);
}
}
int client_serverbrowse_refreshingmasters()
{
return mastersrv_refreshing();
}

View file

@ -13,6 +13,8 @@
#include <engine/e_network.h>
#include "e_linereader.h"
static JOBPOOL hostlookuppool;
static void con_dbg_dumpmem(void *result, void *user_data)
{
mem_debug_dump();
@ -63,6 +65,8 @@ void engine_init(const char *appname)
/* init console and add the console logger */
console_init();
dbg_logger(console_print);
jobs_initpool(&hostlookuppool, 1);
MACRO_REGISTER_COMMAND("dbg_dumpmem", "", con_dbg_dumpmem, 0x0);
@ -224,65 +228,29 @@ void perf_dump(PERFORMACE_INFO *top)
}
/* master server functions */
enum
{
NUM_LOOKUP_THREADS=4,
STATE_PROCESSED=0,
STATE_RESULT,
STATE_QUERYING
};
typedef struct
{
char hostname[128];
NETADDR addr;
/* these are used for lookups */
struct {
NETADDR addr;
int result;
void *thread;
volatile int state;
} lookup;
HOSTLOOKUP lookup;
} MASTER_INFO;
typedef struct
{
int start;
int num;
} THREAD_INFO;
static MASTER_INFO master_servers[MAX_MASTERSERVERS] = {{{0}}};
static THREAD_INFO thread_info[NUM_LOOKUP_THREADS];
static int needs_update = 0;
void lookup_thread(void *user)
{
THREAD_INFO *info = (THREAD_INFO *)user;
int i;
for(i = 0; i < info->num; i++)
{
int index = info->start+i;
master_servers[index].lookup.result = net_host_lookup(master_servers[index].hostname, &master_servers[index].lookup.addr, NETTYPE_IPV4);
master_servers[index].lookup.state = STATE_RESULT;
}
}
static int needs_update = -1;
int mastersrv_refresh_addresses()
{
int i;
dbg_msg("engine/mastersrv", "refreshing master server addresses");
/* spawn threads that does the lookups */
for(i = 0; i < NUM_LOOKUP_THREADS; i++)
{
thread_info[i].start = MAX_MASTERSERVERS/NUM_LOOKUP_THREADS * i;
thread_info[i].num = MAX_MASTERSERVERS/NUM_LOOKUP_THREADS;
master_servers[i].lookup.state = STATE_QUERYING;
master_servers[i].lookup.thread = thread_create(lookup_thread, &thread_info[i]);
}
if(needs_update != -1)
return 0;
dbg_msg("engine/mastersrv", "refreshing master server addresses");
/* add lookup jobs */
for(i = 0; i < MAX_MASTERSERVERS; i++)
engine_hostlookup(&master_servers[i].lookup, master_servers[i].hostname);
needs_update = 1;
return 0;
@ -293,37 +261,23 @@ void mastersrv_update()
int i;
/* check if we need to update */
if(!needs_update)
if(needs_update != 1)
return;
needs_update = 0;
for(i = 0; i < MAX_MASTERSERVERS; i++)
{
if(master_servers[i].lookup.state == STATE_RESULT)
{
/* we got a result from the lookup ready */
if(master_servers[i].lookup.result == 0)
{
master_servers[i].addr = master_servers[i].lookup.addr;
master_servers[i].addr.port = 8300;
}
master_servers[i].lookup.state = STATE_PROCESSED;
}
/* set the needs_update flag if we isn't done */
if(master_servers[i].lookup.state != STATE_PROCESSED)
if(jobs_status(&master_servers[i].lookup.job) != JOBSTATUS_DONE)
needs_update = 1;
else
{
master_servers[i].addr = master_servers[i].lookup.addr;
master_servers[i].addr.port = 8300;
}
}
if(!needs_update)
{
/* make sure to destroy the threads */
for(i = 0; i < NUM_LOOKUP_THREADS; i++)
{
thread_destroy(master_servers[i].lookup.thread);
master_servers[i].lookup.thread = 0;
}
dbg_msg("engine/mastersrv", "saving addresses");
mastersrv_save();
}
@ -436,3 +390,18 @@ int mastersrv_save()
io_close(file);
return 0;
}
int hostlookup_thread(void *user)
{
HOSTLOOKUP *lookup = (HOSTLOOKUP *)user;
net_host_lookup(lookup->hostname, &lookup->addr, NETTYPE_IPV4);
return 0;
}
void engine_hostlookup(HOSTLOOKUP *lookup, const char *hostname)
{
str_copy(lookup->hostname, hostname, sizeof(lookup->hostname));
jobs_add(&hostlookuppool, &lookup->job, hostlookup_thread, lookup);
}

View file

@ -1,5 +1,7 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include "e_jobs.h"
const char *engine_savepath(const char *filename, char *buffer, int max);
void engine_init(const char *appname);
void engine_parse_arguments(int argc, char **argv);
@ -10,6 +12,14 @@ void engine_config_write_stop();
int engine_stress(float probability);
typedef struct HOSTLOOKUP
{
JOB job;
char hostname[128];
NETADDR addr;
} HOSTLOOKUP;
void engine_hostlookup(HOSTLOOKUP *lookup, const char *hostname);
enum
{

View file

@ -535,4 +535,6 @@ enum
void client_serverbrowse_set(NETADDR *addr, int type, int token, SERVER_INFO *info);
int client_serverbrowse_refreshingmasters();
#endif

76
src/engine/e_jobs.c Normal file
View file

@ -0,0 +1,76 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <base/system.h>
#include "e_jobs.h"
void worker_thread(void *user)
{
JOBPOOL *pool = (JOBPOOL *)user;
while(1)
{
JOB *job = 0;
/* fetch job from queue */
lock_wait(pool->lock);
if(pool->first_job)
{
job = pool->first_job;
pool->first_job = pool->first_job->next;
if(pool->first_job)
pool->first_job->prev = 0;
else
pool->last_job = 0;
}
lock_release(pool->lock);
/* do the job if we have one */
if(job)
{
job->status = JOBSTATUS_RUNNING;
job->result = job->func(job->func_data);
job->status = JOBSTATUS_DONE;
}
else
thread_sleep(10);
}
}
int jobs_initpool(JOBPOOL *pool, int num_threads)
{
int i;
/* empty the pool */
mem_zero(pool, sizeof(JOBPOOL));
pool->lock = lock_create();
/* start threads */
for(i = 0; i < num_threads; i++)
thread_create(worker_thread, pool);
return 0;
}
int jobs_add(JOBPOOL *pool, JOB *job, JOBFUNC func, void *data)
{
mem_zero(job, sizeof(JOB));
job->func = func;
job->func_data = data;
lock_wait(pool->lock);
/* add job to queue */
job->prev = pool->last_job;
if(pool->last_job)
pool->last_job->next = job;
pool->last_job = job;
if(!pool->first_job)
pool->first_job = job;
lock_release(pool->lock);
return 0;
}
int jobs_status(JOB *job)
{
return job->status;
}

33
src/engine/e_jobs.h Normal file
View file

@ -0,0 +1,33 @@
typedef int (*JOBFUNC)(void *data);
typedef struct JOB
{
struct JOBPOOL *pool;
struct JOB *prev;
struct JOB *next;
volatile int status;
volatile int result;
JOBFUNC func;
void *func_data;
} JOB;
typedef struct JOBPOOL
{
LOCK lock;
JOB *first_job;
JOB *last_job;
} JOBPOOL;
enum
{
JOBSTATUS_PENDING=0,
JOBSTATUS_RUNNING,
JOBSTATUS_DONE
/*JOBSTATUS_ABORTING,*/
/*JOBSTATUS_ABORTED,*/
};
int jobs_initpool(JOBPOOL *pool, int num_threads);
int jobs_add(JOBPOOL *pool, JOB *job, JOBFUNC func, void *data);
int jobs_status(JOB *job);

View file

@ -41,6 +41,9 @@ enum
NETMSG_SNAPSMALL, /* */
NETMSG_RCON_AUTH_STATUS,/* result of the authentication */
NETMSG_RCON_LINE, /* line that should be printed to the remote console */
NETMSG_AUTH_CHALLANGE, /* */
NETMSG_AUTH_RESULT, /* */
/* sent by client */
NETMSG_READY, /* */
@ -49,6 +52,9 @@ enum
NETMSG_RCON_CMD, /* */
NETMSG_RCON_AUTH, /* */
NETMSG_REQUEST_MAP_DATA,/* */
NETMSG_AUTH_START, /* */
NETMSG_AUTH_RESPONSE, /* */
/* sent by both */
NETMSG_PING,

View file

@ -122,7 +122,7 @@ void MENUS::render_serverbrowser_serverlist(RECT view)
ui_vsplit_r(&view, 15, &view, &scroll);
int num_servers = client_serverbrowse_sorted_num();
int num = (int)(view.h/cols[0].rect.h);
static int scrollbar = 0;
static float scrollvalue = 0;
@ -312,7 +312,10 @@ void MENUS::render_serverbrowser_serverlist(RECT view)
ui_draw_rect(&status, vec4(1,1,1,0.25f), CORNER_B, 5.0f);
ui_vmargin(&status, 50.0f, &status);
char buf[128];
str_format(buf, sizeof(buf), "%d of %d servers, %d players", client_serverbrowse_sorted_num(), client_serverbrowse_num(), num_players);
if(client_serverbrowse_refreshingmasters())
str_format(buf, sizeof(buf), "Refreshing master servers...");
else
str_format(buf, sizeof(buf), "%d of %d servers, %d players", client_serverbrowse_sorted_num(), client_serverbrowse_num(), num_players);
ui_do_label(&status, buf, 14.0f, -1);
}