1
/* GNU Chess 5.0 - input.c - Input thread and related
2
Copyright (c) 2002 Free Software Foundation, Inc.
4
GNU Chess is based on the two research programs
5
Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
7
GNU Chess is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
12
GNU Chess is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with GNU Chess; see the file COPYING. If not, write to
19
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
Boston, MA 02111-1307, USA.
24
cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
29
* All the pthread stuff should be hidden here, all the
30
* readline things, too. (I.e., all the potentially troublesome
45
#ifdef HAVE_LIBREADLINE
46
# ifdef HAVE_READLINE_READLINE_H
47
# include <readline/readline.h>
48
# include <readline/history.h>
50
extern char* readline(char *);
51
extern void add_history(char *);
55
/* Variable used to communicate with the main thread */
56
volatile int input_status = INPUT_NONE;
58
char inputstr[MAXSTR];
61
* The readline getline(), notice that even if we have readline,
62
* it is not used if stdin is not a tty.
65
#ifdef HAVE_LIBREADLINE
66
void getline_readline(char * p)
71
dbg_printf("getline_readline() called, input is >%s<\n", inp ? inp : "NULL");
73
add_history(inputstr);
74
strncpy(inputstr, inp, MAXSTR-1);
75
inputstr[MAXSTR-1] = '\0';
83
#endif /* HAVE_LIBREADLINE */
85
/* The generic input routine */
87
void getline_standard(char *p)
89
if (!(flags & XBOARD)) {
93
fgets(inputstr, MAXSTR, stdin);
96
pthread_t input_thread;
98
/* Mutex and condition variable for thread communication */
100
static pthread_mutex_t input_mutex = PTHREAD_MUTEX_INITIALIZER;
101
static pthread_cond_t input_cond = PTHREAD_COND_INITIALIZER;
102
static pthread_mutex_t wakeup_mutex = PTHREAD_MUTEX_INITIALIZER;
103
static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER;
106
* Posix threads are used to allow efficent polling for
107
* input when the program is pondering.
109
* input_status is a boolean to indicate if a command
110
* is being parsed and processed. It is set by
111
* input function, and must be cleared by the thread
112
* that uses the input.
114
* The main loop may explicitly wait_for_input, or
115
* when pondering will examine the input_status
116
* variable in Iterate.
120
void *input_func(void *arg __attribute__((unused)) )
122
char prompt[MAXSTR] = "";
124
while (!(flags & QUIT)) {
125
if (!(flags & XBOARD)) {
126
sprintf(prompt,"%s (%d) : ",
127
RealSide ? "Black" : "White",
128
(RealGameCnt+1)/2 + 1 );
130
pthread_mutex_lock(&input_mutex);
131
getline_intrl(prompt);
132
input_status = INPUT_AVAILABLE;
133
pthread_cond_signal(&input_cond);
134
pthread_mutex_unlock(&input_mutex);
136
pthread_mutex_lock(&wakeup_mutex);
138
* Posix waits can wake up spuriously
139
* so we must ensure that we keep waiting
140
* until we are woken by something that has
143
while ( input_status == INPUT_AVAILABLE ){
144
pthread_cond_wait(&wakeup_cond, &wakeup_mutex);
146
pthread_mutex_unlock(&wakeup_mutex);
151
void input_wakeup(void)
154
pthread_mutex_lock(&input_mutex);
155
input_status = INPUT_NONE;
156
pthread_mutex_unlock(&input_mutex);
157
pthread_mutex_lock(&wakeup_mutex);
158
pthread_cond_signal(&wakeup_cond);
159
pthread_mutex_unlock(&wakeup_mutex);
162
void wait_for_input(void)
164
// Read without mutex -- whoops
165
while (input_status == INPUT_NONE) {
166
pthread_mutex_lock(&input_mutex);
167
if (input_status == INPUT_NONE)
168
pthread_cond_wait(&input_cond, &input_mutex);
169
pthread_mutex_unlock(&input_mutex);
175
#ifdef HAVE_LIBREADLINE
176
if (isatty(STDIN_FILENO)) {
177
getline_intrl = getline_readline;
180
getline_intrl = getline_standard;
183
getline_intrl = getline_standard;
185
/* Start input thread */
186
pthread_create(&input_thread, NULL, input_func, NULL);
189
void CleanupInput(void)
191
pthread_join(input_thread, NULL);