]> git.pond.sub.org Git - empserver/commitdiff
Simplify checks whether player thread may sleep
authorMarkus Armbruster <armbru@pond.sub.org>
Tue, 28 Apr 2009 18:31:59 +0000 (20:31 +0200)
committerMarkus Armbruster <armbru@pond.sub.org>
Mon, 30 Nov 2009 18:43:18 +0000 (19:43 +0100)
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.

include/player.h
include/server.h
src/lib/player/accept.c
src/lib/player/dispatch.c
src/lib/player/recvclient.c
src/lib/subs/pr.c
src/server/main.c
src/server/update.c

index 8f8eb51b8a9d8aac6783c89c5de60690f6bb5820..6d442e561a71cd64d7cbe68805e5d8851fa6952f 100644 (file)
 #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;
@@ -76,6 +80,7 @@ struct player {
     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 */
index 5b75aec8e10f2b3123fe842a0fb27a08cd7ded82..837e82d2f9a90895afeabcc88f04c07b2324f3ad 100644 (file)
@@ -40,7 +40,6 @@
 
 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];
 
index 638914875ef7b359b4217e17d7e964a9fb5a3d43..1c8c60bc03cbdba91b559d08ffd8e4835cdff182 100644 (file)
@@ -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);
     }
index 157ee144893398e8029aba0b65cec77d82fae94d..a75fda28d959632818cc600933366a6cb599527a 100644 (file)
@@ -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;
 }
index 74a704ce57da03d26048723b68e7f0061090aab3..3b4f9feab716e5e0e7adbc99fa0b2c4591bebe79 100644 (file)
@@ -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
index 01fc13c8ba3af913acb1b67889df41ea2631eea7..876c819e347e30c2430f6e60ece6ea0062e7bb11 100644 (file)
@@ -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)
            ;
     }
 }
index 44a4f9a49e2042f3437354b0ab908f58a37667b7..336eb6a65d1e4c408b910b9271f4481bbdce08f8 100644 (file)
@@ -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");
index 704d6d3d229e7abfbe2423b7095e39a4ade4f2a4..7b4a4b676ee3ef17b4bf9f67a6a19e27eb5477b5 100644 (file)
@@ -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);
 }