Rewrite how updates are triggered (closes #1504036):

(update_init, update_sched, update_run, update_wait): Don't create a
separate UpdateSched thread, run update_sched() in the Update thread.
Run the update by calling update_run() instead of by signalling its
thread.  update_run() replaces update_wait(); it just runs the update
and returns instead of waiting for the signal to update in a loop.
Move initialization of the Update thread's *player to its new thread
entry point.
(update_sem, update_init): Remove update_sem.
(update_thread): New.
(update_init): Initialize it.
(update_forced): New.
(update_trigger, update_force): Wake up update_thread with
update_force set.
(update_sched): Reset it before sleep, test it after sleep so that
schedule checking is only done for scheduled updates, not forced
updates.

(update_sched, update_init): Move sanity test of s_p_etu to
update_init().
This commit is contained in:
Markus Armbruster 2007-02-08 11:54:31 +00:00
parent cea39829af
commit c1eb1bd5d2

View file

@ -48,14 +48,15 @@
#include "prototypes.h" #include "prototypes.h"
#include "server.h" #include "server.h"
empth_sem_t *update_sem; static empth_t *update_thread;
empth_rwlock_t *update_lock; empth_rwlock_t *update_lock;
int update_pending; int update_pending;
time_t update_time; time_t update_time;
static int update_forced;
static void update_sched(void *); static void update_sched(void *);
static void update_force(void *); static void update_force(void *);
static void update_wait(void *unused); static void update_run(void);
static int run_hook(char *cmd, char *name); static int run_hook(char *cmd, char *name);
void void
@ -64,9 +65,14 @@ update_init(void)
struct player *dp; struct player *dp;
int stacksize; int stacksize;
update_sem = empth_sem_create("Update", 0); if (s_p_etu <= 0) {
logerror("bad value for s_p_etu (%d)", s_p_etu);
s_p_etu = 2 * 60;
logerror("setting s_p_etu to %d", s_p_etu);
}
update_lock = empth_rwlock_create("Update"); update_lock = empth_rwlock_create("Update");
if (!update_sem || !update_lock) if (!update_lock)
exit_nomem(); exit_nomem();
dp = player_new(-1); dp = player_new(-1);
@ -76,12 +82,9 @@ update_init(void)
stacksize = 100000 + stacksize = 100000 +
/* finish_sects */ WORLD_X * WORLD_Y * (2 * sizeof(double) + /* finish_sects */ WORLD_X * WORLD_Y * (2 * sizeof(double) +
sizeof(char *)); sizeof(char *));
if (!empth_create(PP_UPDATE, update_wait, stacksize, 0, update_thread = empth_create(PP_UPDATE, update_sched, stacksize, 0,
"Update", dp)) "Update", dp);
exit_nomem(); if (!update_thread)
if (!empth_create(PP_SCHED, update_sched, 50 * 1024, 0,
"UpdateSched", NULL))
exit_nomem(); exit_nomem();
} }
@ -92,12 +95,11 @@ update_sched(void *unused)
int wind; int wind;
time_t now, delta; time_t now, delta;
if (s_p_etu <= 0) { player->proc = empth_self();
logerror("bad value for s_p_etu (%d)", s_p_etu); player->cnum = 0;
s_p_etu = 2 * 60; player->god = 1;
logerror("setting s_p_etu to %d", s_p_etu);
} for (;;) {
while (1) {
time(&now); time(&now);
next_update_time(&now, &update_time, &delta); next_update_time(&now, &update_time, &delta);
if (update_window > 0) { if (update_window > 0) {
@ -108,22 +110,25 @@ update_sched(void *unused)
logerror("Next update at %s", ctime(&update_time)); logerror("Next update at %s", ctime(&update_time));
logerror("Next update in %ld seconds", (long)delta); logerror("Next update in %ld seconds", (long)delta);
/* sleep until update is scheduled to go off */ /* sleep until update is scheduled to go off */
update_forced = 0;
empth_sleep(update_time); empth_sleep(update_time);
time(&now); if (!update_forced) {
now += adj_update; time(&now);
if (!gamehours(now)) { now += adj_update;
logerror("No update permitted (hours restriction)"); if (!gamehours(now)) {
continue; logerror("No update permitted (hours restriction)");
continue;
}
if (!updatetime(&now)) {
logerror("No update wanted");
continue;
}
if (updates_disabled()) {
logerror("Updates disabled...skipping update");
continue;
}
} }
if (!updatetime(&now)) { update_run();
logerror("No update wanted");
continue;
}
if (updates_disabled()) {
logerror("Updates disabled...skipping update");
continue;
}
empth_sem_signal(update_sem);
} }
/*NOTREACHED*/ /*NOTREACHED*/
} }
@ -141,7 +146,8 @@ update_trigger(time_t secs_from_now)
return -1; return -1;
if (secs_from_now == 0) { if (secs_from_now == 0) {
empth_sem_signal(update_sem); update_forced = 1;
empth_wakeup(update_thread);
return 0; return 0;
} }
@ -163,46 +169,38 @@ update_force(void *seconds)
time(&now); time(&now);
empth_sleep(now + *(time_t *)seconds); empth_sleep(now + *(time_t *)seconds);
empth_sem_signal(update_sem); update_forced = 1;
empth_wakeup(update_thread);
free(seconds); free(seconds);
empth_exit(); empth_exit();
} }
/*ARGSUSED*/
static void static void
update_wait(void *unused) update_run(void)
{ {
struct player *p; struct player *p;
player->proc = empth_self(); update_pending = 1;
player->cnum = 0; for (p = player_next(0); p != 0; p = player_next(p)) {
player->god = 1; if (p->state != PS_PLAYING)
continue;
while (1) { if (p->command) {
empth_sem_wait(update_sem); pr_flash(p, "Update aborting command\n");
update_pending = 1; p->aborted = 1;
for (p = player_next(0); p != 0; p = player_next(p)) { empth_wakeup(p->proc);
if (p->state != PS_PLAYING)
continue;
if (p->command) {
pr_flash(p, "Update aborting command\n");
p->aborted = 1;
empth_wakeup(p->proc);
}
} }
empth_rwlock_wrlock(update_lock);
if (*pre_update_hook) {
if (run_hook(pre_update_hook, "pre-update")) {
update_pending = 0;
empth_rwlock_unlock(update_lock);
continue;
}
}
update_main();
update_pending = 0;
empth_rwlock_unlock(update_lock);
} }
/*NOTREACHED*/ empth_rwlock_wrlock(update_lock);
if (*pre_update_hook) {
if (run_hook(pre_update_hook, "pre-update")) {
update_pending = 0;
empth_rwlock_unlock(update_lock);
return;
}
}
update_main();
update_pending = 0;
empth_rwlock_unlock(update_lock);
} }
static int static int