QWindowsPipeWriter: centralize write result handling
Both code paths (write() for the main thread and waitCallback() for the worker thread) use the same logic when processing write results. To avoid code duplication, consolidate the common part for both threads in the startAsyncWriteLocked() function. Change-Id: Ie2663b2ed221e2797a1ecbdb3fcee0ee8f030cc0 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
This commit is contained in:
parent
329683795d
commit
e650ea323f
@ -145,37 +145,19 @@ inline bool QWindowsPipeWriter::writeImpl(Args... args)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
writeBuffer.append(args...);
|
writeBuffer.append(args...);
|
||||||
return writeImplTail(&locker);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QWindowsPipeWriter::writeImplTail(QMutexLocker<QMutex> *locker)
|
|
||||||
{
|
|
||||||
if (writeSequenceStarted)
|
if (writeSequenceStarted)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
stopped = false;
|
stopped = false;
|
||||||
startAsyncWriteLocked();
|
startAsyncWriteLocked(&locker);
|
||||||
|
|
||||||
// Do not post the event, if the write operation will be completed asynchronously.
|
|
||||||
if (!bytesWrittenPending)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!winEventActPosted) {
|
|
||||||
winEventActPosted = true;
|
|
||||||
locker->unlock();
|
|
||||||
QCoreApplication::postEvent(this, new QEvent(QEvent::WinEventAct));
|
|
||||||
} else {
|
|
||||||
locker->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
SetEvent(syncHandle);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Starts a new write sequence. Thread-safety should be ensured by the caller.
|
Starts a new write sequence.
|
||||||
*/
|
*/
|
||||||
void QWindowsPipeWriter::startAsyncWriteLocked()
|
void QWindowsPipeWriter::startAsyncWriteLocked(QMutexLocker<QMutex> *locker)
|
||||||
{
|
{
|
||||||
while (!writeBuffer.isEmpty()) {
|
while (!writeBuffer.isEmpty()) {
|
||||||
// WriteFile() returns true, if the write operation completes synchronously.
|
// WriteFile() returns true, if the write operation completes synchronously.
|
||||||
@ -190,13 +172,29 @@ void QWindowsPipeWriter::startAsyncWriteLocked()
|
|||||||
// Operation has been queued and will complete in the future.
|
// Operation has been queued and will complete in the future.
|
||||||
writeSequenceStarted = true;
|
writeSequenceStarted = true;
|
||||||
SetThreadpoolWait(waitObject, eventHandle, NULL);
|
SetThreadpoolWait(waitObject, eventHandle, NULL);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!writeCompleted(errorCode, numberOfBytesWritten))
|
if (!writeCompleted(errorCode, numberOfBytesWritten))
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not post the event, if the write operation will be completed asynchronously.
|
||||||
|
if (!bytesWrittenPending)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!winEventActPosted) {
|
||||||
|
winEventActPosted = true;
|
||||||
|
locker->unlock();
|
||||||
|
QCoreApplication::postEvent(this, new QEvent(QEvent::WinEventAct));
|
||||||
|
} else {
|
||||||
|
locker->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We set the event only after unlocking to avoid additional context
|
||||||
|
// switches due to the released thread immediately running into the lock.
|
||||||
|
SetEvent(syncHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -228,20 +226,16 @@ void QWindowsPipeWriter::waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID cont
|
|||||||
|
|
||||||
pipeWriter->writeSequenceStarted = false;
|
pipeWriter->writeSequenceStarted = false;
|
||||||
|
|
||||||
if (pipeWriter->writeCompleted(errorCode, numberOfBytesTransfered))
|
if (pipeWriter->writeCompleted(errorCode, numberOfBytesTransfered)) {
|
||||||
pipeWriter->startAsyncWriteLocked();
|
pipeWriter->startAsyncWriteLocked(&locker);
|
||||||
|
|
||||||
if (pipeWriter->lastError == ERROR_SUCCESS && !pipeWriter->winEventActPosted) {
|
|
||||||
pipeWriter->winEventActPosted = true;
|
|
||||||
locker.unlock();
|
|
||||||
QCoreApplication::postEvent(pipeWriter, new QEvent(QEvent::WinEventAct));
|
|
||||||
} else {
|
} else {
|
||||||
|
// The write operation failed, so we must unblock the main thread,
|
||||||
|
// which can wait for the event. We set the event only after unlocking
|
||||||
|
// to avoid additional context switches due to the released thread
|
||||||
|
// immediately running into the lock.
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
|
SetEvent(pipeWriter->syncHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We set the event only after unlocking to avoid additional context
|
|
||||||
// switches due to the released thread immediately running into the lock.
|
|
||||||
SetEvent(pipeWriter->syncHandle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -86,9 +86,8 @@ protected:
|
|||||||
private:
|
private:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline bool writeImpl(Args... args);
|
inline bool writeImpl(Args... args);
|
||||||
bool writeImplTail(QMutexLocker<QMutex> *locker);
|
|
||||||
|
|
||||||
void startAsyncWriteLocked();
|
void startAsyncWriteLocked(QMutexLocker<QMutex> *locker);
|
||||||
static void CALLBACK waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
|
static void CALLBACK waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
|
||||||
PTP_WAIT wait, TP_WAIT_RESULT waitResult);
|
PTP_WAIT wait, TP_WAIT_RESULT waitResult);
|
||||||
bool writeCompleted(DWORD errorCode, DWORD numberOfBytesWritten);
|
bool writeCompleted(DWORD errorCode, DWORD numberOfBytesWritten);
|
||||||
|
Loading…
Reference in New Issue
Block a user