18      handle(INVALID_HANDLE_VALUE),
 
   19      eventHandle(CreateEvent(NULL, FALSE, FALSE, NULL)),
 
   20      syncHandle(CreateEvent(NULL, TRUE, FALSE, NULL)),
 
   23      actualReadBufferSize(0),
 
   25      lastError(ERROR_SUCCESS),
 
   27      readSequenceStarted(
false),
 
   29      readyReadPending(
false),
 
   30      winEventActPosted(
false)
 
   32    ZeroMemory(&overlapped, 
sizeof(OVERLAPPED));
 
   33    overlapped.hEvent = eventHandle;
 
   34    waitObject = CreateThreadpoolWait(waitCallback, 
this, NULL);
 
   35    if (waitObject == NULL)
 
   36        qErrnoWarning(
"QWindowsPipeReader: CreateThreadpollWait failed.");
 
   45    WaitForThreadpoolWaitCallbacks(waitObject, FALSE);
 
   46    CloseThreadpoolWait(waitObject);
 
   47    CloseHandle(eventHandle);
 
   48    CloseHandle(syncHandle);
 
   58    actualReadBufferSize = 0;
 
   59    readyReadPending = 
false;
 
   63    lastError = ERROR_SUCCESS;
 
   72    cancelAsyncRead(Stopped);
 
   82    cancelAsyncRead(Draining);
 
   92    cancelAsyncRead(Stopped);
 
   94    actualReadBufferSize = 0;
 
   98    lastError = ERROR_SUCCESS;
 
  106    if (state != Running)
 
  111    if (readSequenceStarted) {
 
  115        if (!CancelIoEx(
handle, &overlapped)) {
 
  116            const DWORD dwError = GetLastError();
 
  117            if (dwError != ERROR_NOT_FOUND) {
 
  118                qErrnoWarning(dwError, 
"QWindowsPipeReader: CancelIoEx on handle %p failed.",
 
  126            waitForNotification();
 
  128        } 
while (readSequenceStarted);
 
  144    readBufferMaxSize = 
size;
 
  154    return readSequenceStarted || readyReadPending
 
  155           || (lastError != ERROR_SUCCESS && !pipeBroken);
 
  163    return actualReadBufferSize;
 
  175    if (maxlen == 1 && actualReadBufferSize > 0) {
 
  177        actualReadBufferSize--;
 
  181        actualReadBufferSize -= readSoFar;
 
  185        startAsyncReadHelper(&locker);
 
  203    if (actualReadBufferSize > 0) {
 
  205        actualReadBufferSize -= readSoFar;
 
  209        startAsyncReadHelper(&locker);
 
  225    actualReadBufferSize -= skippedSoFar;
 
  228        startAsyncReadHelper(&locker);
 
  229        if (skippedSoFar == 0)
 
  242    return readBuffer.indexOf(
'\n', actualReadBufferSize) >= 0;
 
  251    startAsyncReadHelper(&locker);
 
  256    if (readSequenceStarted || lastError != ERROR_SUCCESS)
 
  260    startAsyncReadLocked();
 
  263    if (!readyReadPending && lastError == ERROR_SUCCESS)
 
  266    if (!winEventActPosted) {
 
  267        winEventActPosted = 
true;
 
  274    SetEvent(syncHandle);
 
  281void QWindowsPipeReader::startAsyncReadLocked()
 
  287    if (bytesToRead == 0)
 
  290    while (lastError == ERROR_SUCCESS) {
 
  291        if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - 
readBuffer.size())) {
 
  292            bytesToRead = readBufferMaxSize - 
readBuffer.size();
 
  293            if (bytesToRead <= 0) {
 
  305        DWORD numberOfBytesRead;
 
  306        DWORD errorCode = ERROR_SUCCESS;
 
  307        if (!ReadFile(
handle, 
ptr, bytesToRead, &numberOfBytesRead, &overlapped)) {
 
  308            errorCode = GetLastError();
 
  309            if (errorCode == ERROR_IO_PENDING) {
 
  312                readSequenceStarted = 
true;
 
  313                SetThreadpoolWait(waitObject, eventHandle, NULL);
 
  318        if (!readCompleted(errorCode, numberOfBytesRead))
 
  323        if (state == Draining) {
 
  341void QWindowsPipeReader::waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID 
context,
 
  342                                      PTP_WAIT wait, TP_WAIT_RESULT waitResult)
 
  350    DWORD numberOfBytesTransfered = 0;
 
  351    DWORD errorCode = ERROR_SUCCESS;
 
  352    if (!GetOverlappedResult(pipeReader->handle, &pipeReader->overlapped,
 
  353                             &numberOfBytesTransfered, FALSE))
 
  354        errorCode = GetLastError();
 
  356    pipeReader->mutex.
lock();
 
  358    pipeReader->readSequenceStarted = 
false;
 
  365    if (pipeReader->lastError == ERROR_SUCCESS && pipeReader->state != Stopped) {
 
  368        if (pipeReader->state == Draining && errorCode == ERROR_OPERATION_ABORTED)
 
  369            errorCode = ERROR_SUCCESS;
 
  371        if (pipeReader->readCompleted(errorCode, numberOfBytesTransfered))
 
  372            pipeReader->startAsyncReadLocked();
 
  374        if (pipeReader->state == Running && !pipeReader->winEventActPosted) {
 
  375            pipeReader->winEventActPosted = 
true;
 
  376            pipeReader->mutex.
unlock();
 
  379            pipeReader->mutex.
unlock();
 
  382        pipeReader->mutex.
unlock();
 
  387    SetEvent(pipeReader->syncHandle);
 
  394bool QWindowsPipeReader::readCompleted(DWORD errorCode, DWORD numberOfBytesRead)
 
  399    if (errorCode == ERROR_SUCCESS || errorCode == ERROR_MORE_DATA) {
 
  400        readyReadPending = 
true;
 
  401        pendingReadBytes += numberOfBytesRead;
 
  402        readBuffer.truncate(actualReadBufferSize + pendingReadBytes);
 
  406    lastError = errorCode;
 
  416        consumePendingAndEmit(
true);
 
  426bool QWindowsPipeReader::consumePendingAndEmit(
bool allowWinActPosting)
 
  428    ResetEvent(syncHandle);
 
  432    if (allowWinActPosting)
 
  433        winEventActPosted = 
false;
 
  435    const bool emitReadyRead = consumePending();
 
  436    const DWORD dwError = lastError;
 
  444    const bool emitPipeClosed = (dwError != ERROR_SUCCESS && !pipeBroken);
 
  451    if (state != Running)
 
  454    if (!emitPipeClosed) {
 
  461        if (alive && dwError != ERROR_BROKEN_PIPE && dwError != ERROR_PIPE_NOT_CONNECTED)
 
  462            emit winError(dwError, 
"QWindowsPipeReader::consumePendingAndEmit"_L1);
 
  467    return emitReadyRead;
 
  474bool QWindowsPipeReader::consumePending()
 
  476    if (readyReadPending) {
 
  477        readyReadPending = 
false;
 
  478        actualReadBufferSize += pendingReadBytes;
 
  479        pendingReadBytes = 0;
 
  492    if (PeekNamedPipe(
handle, 
nullptr, 0, 
nullptr, &bytes, 
nullptr))
 
  495    lastError = GetLastError();
 
  499bool QWindowsPipeReader::waitForNotification()
 
  503        waitRet = WaitForSingleObjectEx(syncHandle, INFINITE, TRUE);
 
  504        if (waitRet == WAIT_OBJECT_0)
 
  508    } 
while (waitRet == WAIT_IO_COMPLETION);
 
  515#include "moc_qwindowspipereader_p.cpp" 
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
 
void unlock() noexcept
Unlocks this mutex locker.
 
void unlock() noexcept
Unlocks the mutex.
 
void lock() noexcept
Locks the mutex.
 
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
 
void stop()
Stops the asynchronous read sequence.
 
bool canReadLine() const
Returns true if a complete line of data can be read from the buffer.
 
qint64 bytesAvailable() const
Returns the number of bytes we've read so far.
 
DWORD checkPipeState()
Returns the number of available bytes in the pipe.
 
bool isReadOperationActive() const
Returns true if async operation is in progress, there is pending data to read, or a read error is pen...
 
qint64 skip(qint64 maxlen)
Skips up to {maxlen} bytes from the internal read buffer.
 
QWindowsPipeReader(QObject *parent=nullptr)
 
void startAsyncRead()
Starts an asynchronous read sequence on the pipe.
 
void stopAndClear()
Stops the asynchronous read sequence.
 
void drainAndStop()
Stops the asynchronous read sequence.
 
qint64 read(char *data, qint64 maxlen)
Copies at most {maxlen} bytes from the internal read buffer to {data}.
 
qint64 readLine(char *data, qint64 maxlen)
Reads a line from the internal buffer, but no more than {maxlen} characters.
 
void winError(ulong, const QString &)
 
void setHandle(HANDLE hPipeReadEnd)
Sets the handle to read from.
 
void setMaxReadBufferSize(qint64 size)
Sets the size of internal read buffer.
 
bool event(QEvent *e) override
Receives notification that the read operation has completed.
 
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
 
void qErrnoWarning(const char *msg,...)
 
Combined button and popup list for selecting options.
 
static ControlElement< T > * ptr(QWidget *widget)
 
constexpr const T & qMin(const T &a, const T &b)
 
constexpr const T & qMax(const T &a, const T &b)
 
GLuint64 GLenum void * handle
 
GLenum GLuint GLintptr GLsizeiptr size
[1]
 
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
 
GLbitfield GLuint readBuffer
 
static const DWORD minReadBufferSize
 
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent