In the source below, objStdIn is a thread object handling stdin:
Code: Select all
bool clsStdInThread::Execute()
{
sfout.Push("# stdin thread is running");
while(true)
{
std::string s;
std::getline(std::cin, s);
if(s.length())
Push(s.c_str());
}
return true;
}
Even stdout is handled by a separate thread, using an object that you see called "sfout", in my source. It collect output strings, protecting them with a mutex (mutOutput). In Satana implementation bDirectOutput is true:
Code: Select all
void clsTSafeOutput::Push(const clsString &Text, bool bCr)
{
if(mutOutput.TryLock())
{
if(bDirectOutput)
{
std::cout << Text.GetString();
if(bCr) std::cout << std::endl;
}else
{
if(!ssOutput.Count()) ssOutput.cAdd(Text);
else *(ssOutput[ssOutput.Count()-1]) += Text;
if(bCr) ssOutput.cAdd("");
}
mutOutput.UnLock();
}
}
Code: Select all
bool clsSatana::Execute()
{
objStdIn.RunJob();
for(bool bOk = true; bOk; )
{
int64_t TickNow = GetTicks();
if(engine.IsRunning())
{
if(TickEnd>0 && TickNow>TickEnd)
{
engine.Stop();
}else
{
int64_t sec = (TickNow-TickLast)/CLOCKS_PER_SEC;
if(sec>=1)
{
TickLast = TickNow;
int64_t sec2end = (TickEnd - TickNow)/CLOCKS_PER_SEC;
}
}
}
else
{
switch(mode)
{
case enModeSet:
break;
case enModePlayWhite:
case enModePlayBlack:
case enModeAutoPlay:
{
clsString sBestMove = engine.GetBestMove(true);
if(sBestMove.Length())
{
eng_clock = eng_clock - ((TickNow - Tick0)*1000)/CLOCKS_PER_SEC;
engine.UserMove(sBestMove);
sfout.Push(clsString("move ") + sBestMove);
}
}
break;
}
usleep(100); // <---- HERE'S THE "PATCH"
}
clsString s = objStdIn.Pop();
if(s.Length())
{
switch(XBoardCommand(s.TokenLeft(' '), s.TokenRight(' ')))
{
case intQuit: bOk = false; break;
}
}
if(bThinkOutput && engine.IsRunning())
{
clsString sPV = engine.GetPV();
if(sPV!=sOldPV)
{
sOldPV = sPV;
sfout.Push(engine.GetPV()
+ " [ms " + clsString(uint64_t((TickEnd - TickNow)*1000)/CLOCKS_PER_SEC)
+ "-" + clsString(uint64_t(eng_clock)) + "]");
}
}
}
return true;
}
My questions are:
- how do you handle separate threads for input/output/engine?
- there is a better way to do it?
Stefano