Simplify checks whether player thread may sleep
A player thread may sleep on input or output, except: (1) While it is executing a C_MOD command, it may only sleep on input. (2) While it is being aborted by the update or shutdown, it may not sleep at all. To find out whether a player thread may sleep on input, code has to check condition (2). It needs do to that in recvclient(). To find out whether it may sleep on output, it has to check both conditions. It needs to do that in pr_player() and upr_player(). The code tracked condition (1) in global variable play_lock_wanted. It checked condition (2) by examining struct player member command. Replace all that by new struct player member may_sleep. Initialize it in player_new(), update it in dispatch(), shutdwn() and update_run(). This makes the tests in recvclient(), pr_player() and upr_player() obvious. play_wrlock_wanted() is now unused, remove it.
This commit is contained in:
parent
bd6d9d53a0
commit
0a4d77e919
8 changed files with 17 additions and 20 deletions
|
@ -89,6 +89,7 @@ player_new(int s)
|
|||
}
|
||||
emp_insque(&lp->queue, &Players);
|
||||
lp->cnum = NATID_BAD;
|
||||
lp->may_sleep = PLAYER_SLEEP_FREELY;
|
||||
lp->curid = -1;
|
||||
time(&lp->curup);
|
||||
}
|
||||
|
|
|
@ -85,6 +85,8 @@ dispatch(char *buf, char *redir)
|
|||
pr("Command not implemented\n");
|
||||
return 0;
|
||||
}
|
||||
player->may_sleep = command->c_flags & C_MOD
|
||||
? PLAYER_SLEEP_ON_INPUT : PLAYER_SLEEP_FREELY;
|
||||
player->command = command;
|
||||
empth_rwlock_rdlock(play_lock);
|
||||
if (redir) {
|
||||
|
@ -109,5 +111,6 @@ dispatch(char *buf, char *redir)
|
|||
}
|
||||
empth_rwlock_unlock(play_lock);
|
||||
player->command = NULL;
|
||||
player->may_sleep = PLAYER_SLEEP_FREELY;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "journal.h"
|
||||
#include "player.h"
|
||||
#include "prototypes.h"
|
||||
#include "server.h"
|
||||
|
||||
/*
|
||||
* Receive a line of input from the current player.
|
||||
|
@ -80,7 +79,9 @@ recvclient(char *cmd, int size)
|
|||
* Flush all queued output before potentially sleeping in
|
||||
* io_input(), to make sure player sees the prompt.
|
||||
*/
|
||||
while (io_output(player->iop, !play_wrlock_wanted) > 0) ;
|
||||
while (io_output(player->iop,
|
||||
player->may_sleep >= PLAYER_SLEEP_ON_INPUT) > 0)
|
||||
;
|
||||
|
||||
/*
|
||||
* If io_output_all() blocked and got unblocked by command
|
||||
|
|
|
@ -244,9 +244,7 @@ pr_player(struct player *pl, int id, char *buf)
|
|||
|
||||
if (player == pl) {
|
||||
while (io_output_if_queue_long(pl->iop,
|
||||
!play_wrlock_wanted
|
||||
&& !(pl->command && (pl->command->c_flags & C_MOD)))
|
||||
> 0)
|
||||
pl->may_sleep == PLAYER_SLEEP_FREELY) > 0)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -302,9 +300,7 @@ upr_player(struct player *pl, int id, char *buf)
|
|||
|
||||
if (player == pl) {
|
||||
while (io_output_if_queue_long(pl->iop,
|
||||
!play_wrlock_wanted
|
||||
&& !(pl->command && (pl->command->c_flags & C_MOD)))
|
||||
> 0)
|
||||
pl->may_sleep == PLAYER_SLEEP_FREELY) > 0)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,13 +86,6 @@ static void loc_NTTerm(void);
|
|||
*/
|
||||
empth_rwlock_t *play_lock;
|
||||
|
||||
/*
|
||||
* Is a thread attempting to take an exclusive play_lock?
|
||||
* Threads holding a shared play_lock must not sleep while this is
|
||||
* true.
|
||||
*/
|
||||
int play_wrlock_wanted;
|
||||
|
||||
static char pidfname[] = "server.pid";
|
||||
|
||||
/* Run as daemon? If yes, detach from controlling terminal etc. */
|
||||
|
@ -421,12 +414,12 @@ shutdwn(int sig)
|
|||
|
||||
logerror("Shutdown commencing (cleaning up threads.)");
|
||||
|
||||
play_wrlock_wanted = 1;
|
||||
for (p = player_next(NULL); p; p = player_next(p)) {
|
||||
if (p->state != PS_PLAYING)
|
||||
continue;
|
||||
pr_flash(p, "Server shutting down...\n");
|
||||
p->state = PS_SHUTDOWN;
|
||||
p->may_sleep = PLAYER_SLEEP_NEVER;
|
||||
p->aborted++;
|
||||
if (p->command) {
|
||||
pr_flash(p, "Shutdown aborting command\n");
|
||||
|
|
|
@ -193,12 +193,12 @@ update_run(void)
|
|||
{
|
||||
struct player *p;
|
||||
|
||||
play_wrlock_wanted = 1;
|
||||
for (p = player_next(NULL); p; p = player_next(p)) {
|
||||
if (p->state != PS_PLAYING)
|
||||
continue;
|
||||
if (p->command) {
|
||||
pr_flash(p, "Update aborting command\n");
|
||||
p->may_sleep = PLAYER_SLEEP_NEVER;
|
||||
p->aborted = 1;
|
||||
empth_wakeup(p->proc);
|
||||
}
|
||||
|
@ -206,14 +206,13 @@ update_run(void)
|
|||
empth_rwlock_wrlock(play_lock);
|
||||
if (*pre_update_hook) {
|
||||
if (run_hook(pre_update_hook, "pre-update")) {
|
||||
play_wrlock_wanted = 0;
|
||||
empth_rwlock_unlock(play_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
update_running = 1;
|
||||
update_main();
|
||||
play_wrlock_wanted = update_running = 0;
|
||||
update_running = 0;
|
||||
empth_rwlock_unlock(play_lock);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue