From: H.G.Muller Date: Sat, 8 Dec 2018 11:00:48 +0000 (+0100) Subject: Let engine thread parse difficult commands X-Git-Tag: v4.0~15 X-Git-Url: http://winboard.nl/cgi-bin?p=uci2wb.git;a=commitdiff_plain;h=33b016e152d6f441cc4b2d7c5cb8ad440f480bc6 Let engine thread parse difficult commands The design of the adapter is completely changed: the engine thread is made responsible for parsing and execution of all commands that cannot be processed during a search. To this end it alternates between reading from the engine (while the engine is searching, or should respond to a 'uci' or 'isready' query) and from the command queue (which is emptied before we dedicate to relaying ponder output). Searches are terminated by the GUI thread when a command arrives that would interrupt the search, so that the engine thread will start looking at the command queue again. Syncing threads to wait for an engine reply is replaced by just doing a (blocking) read for engine output in the same threat, and having the processing routine return once the answer has arrived (and is processed). Instead the Sync pipe is now used to block reading of the command queue when this is empty. This change breaks several of the less elementary commands. Fix command queue --- diff --git a/UCI2WB.c b/UCI2WB.c index 8de43f5..135b3a7 100644 --- a/UCI2WB.c +++ b/UCI2WB.c @@ -42,7 +42,7 @@ #define NONE 2 #define ANALYZE 3 -char move[2000][10], iniPos[256], hashOpt[20], pause, suspended, ponder, post, hasHash, c, sc='c', suffix[81], varOpt, searching, *binary; +char move[2000][10], iniPos[256], hashOpt[20], suspended, ponder, post, hasHash, c, sc='c', suffix[81], varOpt, searching, *binary; int mps, tc, inc, sTime, depth, myTime, hisTime, stm, computer = NONE, memory, oldMem=0, cores, moveNr, lastDepth, lastScore, startTime, debug, flob; int statDepth, statScore, statNodes, statTime, currNr, size, collect, nr, sm, inex, on[500], frc, byo = -1, namOpt, comp; char currMove[20], moveMap[500][10], /* for analyze mode */ canPonder[20], threadOpt[20], varList[8000], anaOpt[20], backLog[10000], checkOptions[8192] = "Ponder"; @@ -164,9 +164,7 @@ void StopPonder(int pondering) { if(!pondering) return; - pause = 1; EPRINT((f, "# stop\n")) fflush(toE); // note: 'pondering' remains set until engine acknowledges 'stop' with 'bestmove' - Sync(PAUSE); // wait for engine to acknowledge 'stop' with 'bestmove'. } void @@ -264,8 +262,8 @@ HandleEngineOutput() DPRINT("# engine said: %s", line), fflush(stdout); if(sscanf(line, "%s", command) != 1) continue; if(!strcmp(command, "bestmove")) { - if(pause == 1) { searching = pause = 0; Sync(WAKEUP); continue; } // bestmove was reply to ponder miss or analysis result; ignore. - else if(searching == 1) { searching = 0; printf("%d 0 0 0 UCI violation! Engine moves during ponder\n", lastDepth+1); continue; } // ignore ponder search + if(searching == 1) { searching = 0; printf("%d 0 0 0 UCI violation! Engine moves during ponder\n", lastDepth+1); return; } // ignore ponder search + else if(searching != 3) { searching = 0; return; } // ponder miss or analysis result; ignore. // move was a move to be played if(p = strstr(line+8, " draw")) *p = 0, printf("offer draw\n"); // UCCI if(strstr(line+9, "resign")) { printf("resign\n"); computer = NONE; } @@ -289,8 +287,8 @@ HandleEngineOutput() Move4GUI(line+9); printf("move %s\n", line+9); // send move to GUI if(move[moveNr][0]) printf("Hint: %s\n", move[moveNr]); - if(pause) { pause = 0; Sync(WAKEUP); } // release commands that came in during think if(lastScore == 100001 && iniPos[0] != 'f') { printf("%s {mate}\n", stm == BLACK ? "1-0" : "0-1"); computer = NONE; } + return; } else if(!strcmp(command, "info")) { int d=0, s=0, t=(GetTickCount() - startTime)/10, n=1; @@ -395,7 +393,7 @@ HandleEngineOutput() if(sscanf(line, "id name %[^\n]", name) == 1) printf("feature myname=\"%s (U%cI2WB)\"\n", name, sc-32); if(sscanf(line, "id version %[^\n]", version) == 1 && *name) printf("feature myname=\"%s %s (U%cI2WB)\"\n", name, version, sc-32); } - else if(!strcmp(command, "readyok")) { pause = 0; Sync(WAKEUP); } // resume processing of GUI commands + else if(!strcmp(command, "readyok")) return; // resume processing of GUI commands else if(sc == 'x'&& !strcmp(command, "ucciok") || sscanf(command, "u%ciok", &c)==1 && c==sc) { char *p = varList, *q = varList; while(*q && *q != '\n') if(!strncmp(q, " var ", 5)) *p++ = ',', q +=5; // replace var keywords by commas @@ -406,7 +404,7 @@ HandleEngineOutput() if(*egts) printf("feature egt=\"%s\"\n", egts+1); printf("feature smp=1 memory=%d done=1\n", hasHash); if(unit == 2) { unit = 1; EPRINT((f, "# setoption usemillisec true\n")) } - Sync(WAKEUP); // done with options + return; // done with options } } } @@ -431,7 +429,7 @@ Move4Engine(char *m) int DoCommand (); char mySide; -char queue[10000], *qStart, *qEnd; +volatile char queue[10000], *qStart, *qEnd; void LaunchSearch() @@ -450,7 +448,7 @@ LaunchSearch() for(i=1; i 0) EPRINT((f, "# setoption name UCI_Chess960 value true\n")) } } else if(!strcmp(command, "undo") && (i=1) || !strcmp(command, "remove") && (i=2)) { - if(searching) StopPonder(1), searching = 0; moveNr = moveNr > i ? moveNr - i : 0; collect = (computer == ANALYZE); sm = 0; } else if(!strcmp(command, ".")) { @@ -614,12 +609,11 @@ DoCommand () inex = 1; line[strlen(line)-1] = sm = 0; // strip LF and clear sm flag for(i=1; i 1) HandleEngineOutput(); // this could leave us (or fall through) pondering + while(qStart == qEnd && searching) HandleEngineOutput(); // relay ponder output until command arrives + Sync(PAUSE); // possibly wait for command silently if engine is idle + if(!DoCommand()) LaunchSearch(); + } } int