X-Git-Url: http://winboard.nl/cgi-bin?p=polyglot.git;a=blobdiff_plain;f=pipe.cpp;h=163e59167b3e494d056328055c568cf2f7d6d5eb;hp=f12a787aa556c26fbeb058838a83171ef2d1372f;hb=5cd5185613348b13625e257efcd7b2f11ca85276;hpb=ad2265d4fc54fc9ba99fc606e6174df34bfb4a0f diff --git a/pipe.cpp b/pipe.cpp index f12a787..163e591 100644 --- a/pipe.cpp +++ b/pipe.cpp @@ -2,135 +2,240 @@ #include "pipe.h" #include "util.h" +// functions + +DWORD WINAPI ThreadProc(LPVOID lpParam){ + PipeStruct *p=(PipeStruct *) lpParam; + while(!p->EOF_()){ + p->ReadInput(); + } + return 0; +} + + + void PipeStruct::Open(const char *szProcFile) { - DWORD dwMode; - HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite; - SECURITY_ATTRIBUTES sa; - STARTUPINFO si; - PROCESS_INFORMATION pi; - state=0; - if (szProcFile == NULL) { - hInput = GetStdHandle(STD_INPUT_HANDLE); - hOutput = GetStdHandle(STD_OUTPUT_HANDLE); - bConsole = GetConsoleMode(hInput, &dwMode); - state|=PIPE_ACTIVE; - - } else { - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0); - CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0); - si.cb = sizeof(STARTUPINFO); - si.lpReserved = si.lpDesktop = si.lpTitle = NULL; - si.dwFlags = STARTF_USESTDHANDLES; - si.cbReserved2 = 0; - si.lpReserved2 = NULL; - si.hStdInput = hStdinRead; - si.hStdOutput = hStdoutWrite; - si.hStdError = hStdoutWrite; - if(CreateProcess(NULL, (LPSTR) szProcFile, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)){ - state|=PIPE_ACTIVE; - hProcess=pi.hProcess; - CloseHandle(pi.hThread); - CloseHandle(hStdinRead); - CloseHandle(hStdoutWrite); - hInput = hStdoutRead; - hOutput = hStdinWrite; - bConsole = FALSE; + DWORD dwMode; + HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite; + SECURITY_ATTRIBUTES sa; + STARTUPINFO si; + PROCESS_INFORMATION pi; + state=0; + if (szProcFile == NULL) { + hInput = GetStdHandle(STD_INPUT_HANDLE); + hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + bConsole = GetConsoleMode(hInput, &dwMode); + bPipe=FALSE; + } else { + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0); + CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0); + si.cb = sizeof(STARTUPINFO); + si.lpReserved = si.lpDesktop = si.lpTitle = NULL; + si.dwFlags = STARTF_USESTDHANDLES; + si.cbReserved2 = 0; + si.lpReserved2 = NULL; + si.hStdInput = hStdinRead; + si.hStdOutput = hStdoutWrite; + si.hStdError = hStdoutWrite; + if(CreateProcess(NULL, + (LPSTR) szProcFile, + NULL, + NULL, + TRUE, + DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, + NULL, + NULL, + &si, + &pi)){ + hProcess=pi.hProcess; + CloseHandle(pi.hThread); + CloseHandle(hStdinRead); + CloseHandle(hStdoutWrite); + hInput = hStdoutRead; + hOutput = hStdinWrite; + bConsole = FALSE; + bPipe=TRUE; + }else{ + my_fatal("PipeStruct::Open(): %s",my_error()); + } } - } - if (bConsole) { - SetConsoleMode(hInput, dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT)); - FlushConsoleInputBuffer(hInput); - } else { - nBytesLeft = 0; - } - nReadEnd = 0; + if (bConsole) { + SetConsoleMode(hInput, + dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT)); + FlushConsoleInputBuffer(hInput); + } + nReadEnd = 0; + InitializeCriticalSection(&CriticalSection); + hEvent=CreateEvent(NULL, // default security + FALSE, // auto reset + FALSE, // not signaled + NULL // nameless + ); + hThread=CreateThread(NULL, // default security + 0, // default stacksize + ThreadProc, // worker function + this, // tell worker about ourselves + 0, // run immediately + NULL // nameless + ); + + set_Active(); } + void PipeStruct::Close(void) const { - CloseHandle(hOutput); + CloseHandle(hOutput); } void PipeStruct::Kill(void) const { - CloseHandle(hInput); - CloseHandle(hOutput); - DWORD lpexit; - - if(GetExitCodeProcess(hProcess,&lpexit)){ - if(lpexit==STILL_ACTIVE) - //must be java,hammer it down! - TerminateProcess(hProcess,lpexit); - } + CloseHandle(hInput); + CloseHandle(hOutput); + DWORD lpexit; + + if(GetExitCodeProcess(hProcess,&lpexit)){ + if(lpexit==STILL_ACTIVE) + //must be java,hammer it down! + TerminateProcess(hProcess,lpexit); + } CloseHandle(hProcess); } bool PipeStruct::EOF_(void){ // EOF is defined - return state&PIPE_EOF; + int ret; + EnterCriticalSection(&CriticalSection); + ret=state&PIPE_EOF; + LeaveCriticalSection(&CriticalSection); + return ret; +} + +void PipeStruct::set_EOF_(void){ + EnterCriticalSection(&CriticalSection); + state|=PIPE_EOF; + LeaveCriticalSection(&CriticalSection); } bool PipeStruct::Active(void){ - return state&PIPE_ACTIVE; + int ret; + EnterCriticalSection(&CriticalSection); + ret=state&PIPE_ACTIVE; + LeaveCriticalSection(&CriticalSection); + return ret; } -void PipeStruct::ReadInput(void) { - DWORD dwBytes; - if(ReadFile(hInput, szBuffer + nReadEnd, LINE_INPUT_MAX_CHAR - nReadEnd, &dwBytes, NULL)){ - nReadEnd += dwBytes; - if (nBytesLeft > 0) { - nBytesLeft -= dwBytes; - } - }else{ - state|=PIPE_EOF; // if we are here there should be data! - } +void PipeStruct::set_Active(void){ + EnterCriticalSection(&CriticalSection); + state|=PIPE_ACTIVE; + LeaveCriticalSection(&CriticalSection); } -bool PipeStruct::CheckInput(void) { - DWORD dwEvents, dwBytes; - if (bConsole) { // a tty, or an un-redirected handle - GetNumberOfConsoleInputEvents(hInput, &dwEvents); - if (dwEvents > 1) { - return TRUE; - } else { - return FALSE; + + +int PipeStruct::ReadLine(void){ + DWORD dwBytes; + int ret; + int start=0; + int start1; + + if(!bPipe){ + fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR,stdin); + start=strlen(lpReadBuffer); + if(!start){ + set_EOF_(); + lpReadBuffer[0]='\0'; + } + return start; + }else{ + while(TRUE){ + // Unfortunately we need to use polling here. + // Otherwise Windows returns single bytes if + // the engine runs at low priority. + // This kills performance. + while(TRUE){ + ret=PeekNamedPipe(hInput, + NULL, // don't read anything yet + 0, // no buffer + NULL, // no we don't read anything! + &dwBytes,// now we're talking + NULL); // nono we don't read anything + if(!ret){ + set_EOF_(); + lpReadBuffer[0]='\0'; + return 0; + } + if(dwBytes>0){ + break; + }else{ + Idle(); + } + + } + ret=ReadFile(hInput, + lpReadBuffer+start, + LINE_INPUT_MAX_CHAR-start, + &dwBytes, + NULL); + if(!ret){ + set_EOF_(); + lpReadBuffer[0]='\0'; + return 0; + }else{ + start1=start; + start+=dwBytes; + if (memchr(lpReadBuffer+start1, '\n', dwBytes)){ + lpReadBuffer[start]='\0'; + return start; + } + } + } } - } else { // a handle redirected to a pipe or a file - if (nBytesLeft > 0) { - return TRUE; - } else { - if (PeekNamedPipe(hInput, NULL, 0, NULL, &dwBytes, NULL)) { - nBytesLeft = dwBytes; - return nBytesLeft > 0; // a pipe - } else { - return TRUE; // a file, always TRUE +} + +void PipeStruct::ReadInput(void) { + DWORD dwBytes; + int ret; + ret=ReadLine(); + EnterCriticalSection(&CriticalSection); + if(!EOF_()){ + if(ret+nReadEnd>=LINE_INPUT_MAX_CHAR){ + my_fatal("PipeStruct::ReadInput(): buffer overflow\n"); } - } + memcpy(lpBuffer+nReadEnd,lpReadBuffer,ret); + nReadEnd += ret; } + LeaveCriticalSection(&CriticalSection); + SetEvent(hEvent); } void PipeStruct::LineOutput(const char *szLineStr) const { DWORD dwBytes; int nStrLen; char szWriteBuffer[LINE_INPUT_MAX_CHAR]; - nStrLen = strlen(szLineStr); - memcpy(szWriteBuffer, szLineStr, nStrLen); - szWriteBuffer[nStrLen] = '\r'; - szWriteBuffer[nStrLen + 1] = '\n'; - WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL); + if(bPipe){ + nStrLen = strlen(szLineStr); + memcpy(szWriteBuffer, szLineStr, nStrLen); + szWriteBuffer[nStrLen] = '\r'; + szWriteBuffer[nStrLen + 1] = '\n'; + WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL); + }else{ + printf("%s\n",szLineStr); + fflush(stdout); + } } - - bool PipeStruct::GetBuffer(char *szLineStr) { char *lpFeedEnd; int nFeedEnd; - lpFeedEnd = (char *) memchr(szBuffer, '\n', nReadEnd); + int ret; + EnterCriticalSection(&CriticalSection); + lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd); if (lpFeedEnd == NULL) { - return FALSE; + ret=FALSE; } else { - nFeedEnd = lpFeedEnd - szBuffer; - memcpy(szLineStr, szBuffer, nFeedEnd); + nFeedEnd = lpFeedEnd - lpBuffer; + memcpy(szLineStr, lpBuffer, nFeedEnd); if (szLineStr[nFeedEnd - 1] == '\r') { szLineStr[nFeedEnd - 1] = '\0'; } else { @@ -138,32 +243,20 @@ bool PipeStruct::GetBuffer(char *szLineStr) { } nFeedEnd ++; nReadEnd -= nFeedEnd; - memcpy(szBuffer, szBuffer + nFeedEnd, nReadEnd); - return TRUE; + memcpy(lpBuffer, lpBuffer + nFeedEnd, nReadEnd); + ret=TRUE; } + LeaveCriticalSection(&CriticalSection); + return ret; } -bool PipeStruct::LineInput(char *szLineStr) { - if (GetBuffer(szLineStr)) { - return TRUE; - } - if (CheckInput()) { - ReadInput(); - if (GetBuffer(szLineStr)) { - return TRUE; - } else { - if (nReadEnd == LINE_INPUT_MAX_CHAR) { - memcpy(szLineStr, szBuffer, LINE_INPUT_MAX_CHAR - 1); - szLineStr[LINE_INPUT_MAX_CHAR - 1] = '\0'; - szBuffer[0] = szBuffer[LINE_INPUT_MAX_CHAR - 1]; - nReadEnd = 1; - return TRUE; - } else { - return FALSE; - } +void PipeStruct::LineInput(char *szLineStr) { + while(!EOF_()){ + if (GetBuffer(szLineStr)) { + break; + }else{ + WaitForSingleObject(hEvent,INFINITE); + } } - } else { - return FALSE; - } } #endif