Reading GUI Input During Search

Discussion of chess software programming and technical issues.

Moderator: Ras

oriyonay
Posts: 32
Joined: Tue Jun 01, 2021 5:46 am
Full name: ori yonay

Reading GUI Input During Search

Post by oriyonay »

Hello again, my wonderful friends!
I've been trying to replace my current VICE-based read_input() function (which is weird and not cross-platform) with a much simpler one. The goal of the function (called once every 2048 nodes searched) is to read the current buffer, and if the user/GUI entered anything, respond appropriately. This is what I have so far:

Code: Select all

void read_input() {
    char input[256];
    if (!fgets(input, 256, stdin)) return;

    // replace first newline with terminating character:
    char* endc = strchr(input, '\n');
    if (endc) *endc = 0;

    // if nothing was entered, return:
    if (!strlen(input)) return;

    // if the user entered something, stop the search:
    stop_search = true;

    // if the user typed 'quit' or 'stop', quit the program:
    if (!strncmp(input, "quit", 4) || !strncmp(input, "stop", 4)) {
        quit_flag = true;
   }
}
Which doesn't work (my guess is because fgets() waits for user input...) - I'm sure all of you have figured out ways I haven't thought of, and I'd love to hear it all!

- Ori :)
yeni_sekme
Posts: 40
Joined: Mon Mar 01, 2021 7:51 pm
Location: İstanbul, Turkey
Full name: Ömer Faruk Tutkun

Re: Reading GUI Input During Search

Post by yeni_sekme »

Yes, fgets is a blocking read. I copy-pasted VICE code to solve the problem but If there is a simpler or better way, I would be glad to learn.
mar
Posts: 2655
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Reading GUI Input During Search

Post by mar »

I wonder why the anti-pattern of polling commands inside search is still prevalent :shock:
just move your search logic into a separate thread and then you can have keep your blocking read in the main thread,
this is also more flexible - or you can keep on copy-pasting from VICE, your call
User avatar
hgm
Posts: 28353
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Reading GUI Input During Search

Post by hgm »

Fairy-Max uses the following code section for platform-dependent stuff:

Code: Select all

#ifdef WIN32 
#    include <windows.h>
#    define CPUtime 1000.*clock
     int Input()
     {  // checks for waiting input in pipe
	static int init; static HANDLE inp; DWORD cnt;
	if(!init) inp = GetStdHandle(STD_INPUT_HANDLE);
	if(!PeekNamedPipe(inp, NULL, 0, NULL, &cnt, NULL)) return 1;
	return cnt;
    }
#else
#    include <sys/time.h>
#    include <sys/times.h>
#    include <sys/ioctl.h>
#    include <unistd.h>
     int GetTickCount() // with thanks to Tord
     {	struct timeval t;
	gettimeofday(&t, NULL);
	return t.tv_sec*1000 + t.tv_usec/1000;
     }
     double CPUtime()
     {  // get CPU time used by process, converted to 'MILLICLOCKS'
	struct tms cpuTimes;
	static int cps = 0;
	if(!cps) cps = sysconf(_SC_CLK_TCK);
	times(&cpuTimes);
	return ((double)(cpuTimes.tms_utime + cpuTimes.tms_stime) * CLOCKS_PER_SEC * 1000)/cps;
     }
     int Input()
     {
	int cnt;
	if(ioctl(0, FIONREAD, &cnt)) return 1;
	return cnt;
     }
#endif
There is one caveat, though; the stream input functions might buffer stuff as well. In which case it is still waiting to be read, but no longer visible in the pipe through Input(). In Fairy-Max I solve this by not checking for input after commands that will always be followed immediately by another command (time and otim, which are only sent before go or usermove), but read on immediately after those. This is a bit flakey. I assume a more fundamental solution would be to disable buffering in the input stream.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Reading GUI Input During Search

Post by mvanthoor »

mar wrote: Fri Jan 14, 2022 8:14 am I wonder why the anti-pattern of polling commands inside search is still prevalent :shock:
just move your search logic into a separate thread and then you can have keep your blocking read in the main thread,
this is also more flexible - or you can keep on copy-pasting from VICE, your call
This.

My engine uses 4 threads:

- the engine / main thread (which is basically the "spider in the web"-thread that keeps everything together)
- search thread
- input thread
- output thread

The input thread sends its stuff to the engine / main thread, which then decides what should be done with it. (start/stop the search, quit the engine, send a reply through the output thread,, etc, etc.) The search thread is the same; it sends its results to the main thread, which then handles it (executing the best move on the engine board, sending it as "bestmove" through the output thread, etc.)

Rustic's high-level overview is here: https://rustic-chess.org/introduction/design.html

Image

The one thing that is not immediately apparent is that the UCI and XBoard parts both contain two threads: one for input, one for output. I still have to change that in the overview. (But it is perfectly possible to use a single thread for both input and output. I just decided to split it up so I have one thread for one purpose.)
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
hgm
Posts: 28353
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Reading GUI Input During Search

Post by hgm »

I don't see any advantage for having separate threads for output. Output calls are non-blocking, and eventually the output is generated by the engine. It would have to be communicated by the output thread, and it is not obvious to me that this would be any faster than immediately outputting it.
User avatar
Ras
Posts: 2696
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: Reading GUI Input During Search

Post by Ras »

hgm wrote: Fri Jan 14, 2022 2:12 pmIt would have to be communicated by the output thread, and it is not obvious to me that this would be any faster than immediately outputting it.
I'd assume additional time loss due to thread switches especially when loading the CPU 100% and at short time controls like 1s/game.
Rasmus Althoff
https://www.ct800.net
User avatar
Roland Chastain
Posts: 680
Joined: Sat Jun 08, 2013 10:07 am
Location: France
Full name: Roland Chastain

Re: Reading GUI Input During Search

Post by Roland Chastain »

mar wrote: Fri Jan 14, 2022 8:14 am I wonder why the anti-pattern of polling commands inside search is still prevalent :shock:
just move your search logic into a separate thread and then you can have keep your blocking read in the main thread
This is what I was about to say. In my Pascal engines I read input in the main thread, with the standard ReadLn procedure, and it works perfectly. I see no need for complicated things like PeekNamedPipe and other. But maybe I miss something...
Qui trop embrasse mal étreint.
Richard Allbert
Posts: 794
Joined: Wed Jul 19, 2006 9:58 am

Re: Reading GUI Input During Search

Post by Richard Allbert »

mar wrote: Fri Jan 14, 2022 8:14 am I wonder why the anti-pattern of polling commands inside search is still prevalent :shock:
just move your search logic into a separate thread and then you can have keep your blocking read in the main thread,
this is also more flexible - or you can keep on copy-pasting from VICE, your call
You’re right, I’ve updated Vice to use a thread for input.

I’ll release when I’ve had time to make the videos.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Reading GUI Input During Search

Post by mvanthoor »

hgm wrote: Fri Jan 14, 2022 2:12 pm I don't see any advantage for having separate threads for output. Output calls are non-blocking, and eventually the output is generated by the engine. It would have to be communicated by the output thread, and it is not obvious to me that this would be any faster than immediately outputting it.
The advantage is that the engine doesn't print its output where-ever it happens to be needed. I've seen lots of engines with output such as:

Code: Select all

if (xboard) {
	....
} else if (winboard) {
	...
} else {
	....
}
scattered throughout the code, or a function that makes that distinction for every possible output.

I have a function "send_to_gui(...)", which outputs through the output thread of communication module. The engine doesn't have to know anything about whatever protocol; it just sends the stuff to the output thread and the communication module handles the output format automatically. Therefore, if I ever have to add a protocol (and I might, because I'm thinking to use a search-less version of my engine as a backend for a GUI), all the input-output stuff can be handled in the communication component. The engine never has to change.

I suppose I could have written the output part to not use a thread, but then it would be different from the input part with regard to architecture and programming style, and I didn't want that.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL