15 eventHandle(CreateEvent(NULL, FALSE, FALSE, NULL)),
16 syncHandle(CreateEvent(NULL, TRUE, FALSE, NULL)),
18 pendingBytesWrittenValue(0),
19 lastError(ERROR_SUCCESS),
22 writeSequenceStarted(
false),
23 bytesWrittenPending(
false),
24 winEventActPosted(
false)
26 ZeroMemory(&overlapped,
sizeof(OVERLAPPED));
27 overlapped.hEvent = eventHandle;
28 waitObject = CreateThreadpoolWait(waitCallback,
this, NULL);
29 if (waitObject == NULL)
30 qErrnoWarning(
"QWindowsPipeWriter: CreateThreadpollWait failed.");
36 CloseThreadpoolWait(waitObject);
37 CloseHandle(eventHandle);
38 CloseHandle(syncHandle);
51 startAsyncWriteHelper(&locker);
65 if (writeSequenceStarted) {
68 SetThreadpoolWait(waitObject, NULL, NULL);
69 if (!CancelIoEx(
handle, &overlapped)) {
70 const DWORD dwError = GetLastError();
71 if (dwError != ERROR_NOT_FOUND) {
72 qErrnoWarning(dwError,
"QWindowsPipeWriter: CancelIoEx on handle %p failed.",
76 writeSequenceStarted =
false;
80 WaitForThreadpoolWaitCallbacks(waitObject, TRUE);
89 return writeBuffer.size() + pendingBytesWrittenValue;
97 return completionState == NoError &&
bytesToWrite() != 0;
105 if (completionState != WriteDisabled)
114 if (completionState != WriteDisabled)
118template <
typename... Args>
119inline void QWindowsPipeWriter::writeImpl(Args...
args)
125 if (writeSequenceStarted || (lastError != ERROR_SUCCESS))
132 if (
handle != INVALID_HANDLE_VALUE)
133 startAsyncWriteHelper(&locker);
138 startAsyncWriteLocked();
141 if (!bytesWrittenPending && lastError == ERROR_SUCCESS)
144 notifyCompleted(locker);
150void QWindowsPipeWriter::startAsyncWriteLocked()
156 DWORD numberOfBytesWritten;
157 DWORD errorCode = ERROR_SUCCESS;
159 &numberOfBytesWritten, &overlapped)) {
160 errorCode = GetLastError();
161 if (errorCode == ERROR_IO_PENDING) {
163 writeSequenceStarted =
true;
164 SetThreadpoolWait(waitObject, eventHandle, NULL);
169 if (!writeCompleted(errorCode, numberOfBytesWritten))
178void QWindowsPipeWriter::waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID
context,
179 PTP_WAIT wait, TP_WAIT_RESULT waitResult)
187 DWORD numberOfBytesTransfered = 0;
188 DWORD errorCode = ERROR_SUCCESS;
189 if (!GetOverlappedResult(pipeWriter->handle, &pipeWriter->overlapped,
190 &numberOfBytesTransfered, FALSE))
191 errorCode = GetLastError();
198 if (pipeWriter->stopped)
201 pipeWriter->writeSequenceStarted =
false;
203 if (pipeWriter->writeCompleted(errorCode, numberOfBytesTransfered))
204 pipeWriter->startAsyncWriteLocked();
208 pipeWriter->notifyCompleted(&locker);
215bool QWindowsPipeWriter::writeCompleted(DWORD errorCode, DWORD numberOfBytesWritten)
219 bytesWrittenPending =
true;
220 pendingBytesWrittenValue += numberOfBytesWritten;
223 case ERROR_PIPE_NOT_CONNECTED:
224 case ERROR_OPERATION_ABORTED:
228 qErrnoWarning(errorCode,
"QWindowsPipeWriter: write failed.");
234 lastError = errorCode;
243 if (!winEventActPosted) {
244 winEventActPosted =
true;
253 SetEvent(syncHandle);
262 consumePendingAndEmit(
true);
272bool QWindowsPipeWriter::consumePendingAndEmit(
bool allowWinActPosting)
274 ResetEvent(syncHandle);
278 if (allowWinActPosting)
279 winEventActPosted =
false;
281 const qint64 numberOfBytesWritten = pendingBytesWrittenValue;
282 const bool emitBytesWritten = bytesWrittenPending;
283 if (emitBytesWritten) {
284 bytesWrittenPending =
false;
285 pendingBytesWrittenValue = 0;
287 const DWORD dwError = lastError;
299 if (dwError != ERROR_SUCCESS && completionState == NoError) {
301 completionState = ErrorDetected;
302 if (emitBytesWritten)
306 completionState = WriteDisabled;
309 }
else if (emitBytesWritten) {
313 return emitBytesWritten;
318#include "moc_qwindowspipewriter_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 write sequence.
QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent=nullptr)
void bytesWritten(qint64 bytes)
bool isWriteOperationActive() const
Returns true if async operation is in progress.
void setHandle(HANDLE hPipeWriteEnd)
Assigns the handle to this writer.
bool event(QEvent *e) override
Receives notification that the write operation has completed.
void write(const QByteArray &ba)
Writes a shallow copy of ba to the internal buffer.
qint64 bytesToWrite() const
Returns the number of bytes that are waiting to be written.
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
static CompletionState completionState(StatementList *list)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent