#define CAP bit(6)
#define MONEY bit(7)
+enum player_sleep {
+ PLAYER_SLEEP_NEVER, PLAYER_SLEEP_ON_INPUT, PLAYER_SLEEP_FREELY
+};
+
struct player {
struct emp_qelem queue;
empth_t *proc;
int simulation; /* e.g. budget command */
double dolcost;
time_t curup; /* when last input was received */
+ enum player_sleep may_sleep; /* when may thread sleep? */
int aborted; /* interrupt cookie or EOF received? */
int eof; /* EOF (cookie or real) received? */
int recvfail; /* #recvclient() failures */
extern int shutdown_pending;
extern empth_rwlock_t *play_lock;
-extern int play_wrlock_wanted;
extern int update_running;
extern time_t update_time[UPDATE_TIME_LEN];
}
emp_insque(&lp->queue, &Players);
lp->cnum = NATID_BAD;
+ lp->may_sleep = PLAYER_SLEEP_FREELY;
lp->curid = -1;
time(&lp->curup);
}
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) {
}
empth_rwlock_unlock(play_lock);
player->command = NULL;
+ player->may_sleep = PLAYER_SLEEP_FREELY;
return 0;
}
#include "journal.h"
#include "player.h"
#include "prototypes.h"
-#include "server.h"
/*
* Receive a line of input from the current player.
* 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
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)
;
}
}
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)
;
}
}
*/
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. */
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");
{
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);
}
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);
}