/* Returns true if EAGAIN encountered. Emits (or queues) bytesWritten for any buffers written.
 * If stopAfterWritingOneBuffer is true, return immediately if a single buffer is written, rather than
 * attempting to drain the whole queue.
 * Doesn't modify notifier.
 */
bool VirtualSerialDevice::tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags)
{
    while (pendingWrites.count() > 0) {
        // Try writing everything we've got, until we hit EAGAIN
        const QByteArray& data = pendingWrites[0];
        qint64 bytesWritten;
        bool needToWait = tryWrite(data.constData(), data.size(), bytesWritten);
        if (needToWait) {
            if (bytesWritten > 0) {
                // We wrote some of the data, update the pending queue
                QByteArray remainder = data.mid(bytesWritten);
                pendingWrites.removeFirst();
                pendingWrites.insert(0, remainder);
            }
            return needToWait;
        } else {
            pendingWrites.removeFirst();
            if (flags & EmitBytesWrittenAsync) {
                emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
            } else {
                emitBytesWrittenIfNeeded(locker, bytesWritten);
            }
            if (flags & StopAfterWritingOneBuffer) return false;
            // Otherwise go round loop again
        }
    }
    return false; // no EAGAIN encountered
}
void VirtualSerialDevice::doWriteCompleted(QMutexLocker &locker)
{
    // Must be locked on entry
    ResetEvent(d->writeOverlapped.hEvent);

    qint64 len = pendingWrites.first().length();
    pendingWrites.removeFirst();

    if (pendingWrites.count() > 0) {
        // Get the next write started before notifying in case client calls waitForBytesWritten in their slot
        writeNextBuffer(locker);
    }

    emitBytesWrittenIfNeeded(locker, len);
}