101 |
static pthread_mutex_t wakeup_mutex = PTHREAD_MUTEX_INITIALIZER; |
static pthread_mutex_t wakeup_mutex = PTHREAD_MUTEX_INITIALIZER; |
102 |
static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER; |
static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER; |
103 |
|
|
104 |
|
/* |
105 |
|
* Posix threads are used to allow efficent polling for |
106 |
|
* input when the program is pondering. |
107 |
|
* |
108 |
|
* input_status is a boolean to indicate if a command |
109 |
|
* is being parsed and processed. It is set by |
110 |
|
* input function, and must be cleared by the thread |
111 |
|
* that uses the input. |
112 |
|
* |
113 |
|
* The main loop may explicitly wait_for_input, or |
114 |
|
* when pondering will examine the input_status |
115 |
|
* variable in Iterate. |
116 |
|
* |
117 |
|
*/ |
118 |
|
|
119 |
void *input_func(void *arg __attribute__((unused)) ) |
void *input_func(void *arg __attribute__((unused)) ) |
120 |
{ |
{ |
121 |
char prompt[MAXSTR] = ""; |
char prompt[MAXSTR] = ""; |
127 |
(RealGameCnt+1)/2 + 1 ); |
(RealGameCnt+1)/2 + 1 ); |
128 |
} |
} |
129 |
pthread_mutex_lock(&input_mutex); |
pthread_mutex_lock(&input_mutex); |
|
input_status = INPUT_NONE; |
|
130 |
getline(prompt); |
getline(prompt); |
131 |
input_status = INPUT_AVAILABLE; |
input_status = INPUT_AVAILABLE; |
132 |
pthread_cond_signal(&input_cond); |
pthread_cond_signal(&input_cond); |
133 |
pthread_mutex_unlock(&input_mutex); |
pthread_mutex_unlock(&input_mutex); |
134 |
|
|
135 |
pthread_mutex_lock(&wakeup_mutex); |
pthread_mutex_lock(&wakeup_mutex); |
136 |
pthread_cond_wait(&wakeup_cond, &wakeup_mutex); |
/* |
137 |
|
* Posix waits can wake up spuriously |
138 |
|
* so we must ensure that we keep waiting |
139 |
|
* until we are woken by something that has |
140 |
|
* consumed the input |
141 |
|
*/ |
142 |
|
while ( input_status == INPUT_AVAILABLE ){ |
143 |
|
pthread_cond_wait(&wakeup_cond, &wakeup_mutex); |
144 |
|
} |
145 |
pthread_mutex_unlock(&wakeup_mutex); |
pthread_mutex_unlock(&wakeup_mutex); |
146 |
} |
} |
147 |
return NULL; |
return NULL; |
150 |
void input_wakeup(void) |
void input_wakeup(void) |
151 |
{ |
{ |
152 |
|
|
153 |
if ( pthread_mutex_trylock(&input_mutex) == 0 ){ |
pthread_mutex_lock(&input_mutex); |
154 |
if ( input_status == INPUT_AVAILABLE ){ |
input_status = INPUT_NONE; |
155 |
input_status = INPUT_NONE; |
pthread_mutex_unlock(&input_mutex); |
|
pthread_mutex_unlock(&input_mutex); |
|
|
} |
|
|
} |
|
156 |
pthread_mutex_lock(&wakeup_mutex); |
pthread_mutex_lock(&wakeup_mutex); |
157 |
pthread_cond_signal(&wakeup_cond); |
pthread_cond_signal(&wakeup_cond); |
158 |
pthread_mutex_unlock(&wakeup_mutex); |
pthread_mutex_unlock(&wakeup_mutex); |