Add an option to flush writes.

There is a bug with QLocalSockets on Windows where data will be silently
dropped if two consecutive writes are performed without flushing and the
remote end hasn't read all the data between the two (see
https://bugreports.qt.io/browse/QTBUG-18385). Since qmsgpack performs
several write operations as part of a single stream output, it must allow
callers to specify whether to flush writes in order to work around this
bug.
This commit is contained in:
Matthew Stickney
2017-02-27 17:32:49 -05:00
parent 067c72767a
commit ca56d9e362
2 changed files with 27 additions and 4 deletions

View File

@ -24,15 +24,15 @@
return retVal;
MsgPackStream::MsgPackStream() :
dev(0), owndev(false), q_status(Ok)
dev(0), owndev(false), q_status(Ok), flushWrites(false)
{ }
MsgPackStream::MsgPackStream(QIODevice *d) :
dev(d), owndev(false), q_status(Ok)
dev(d), owndev(false), q_status(Ok), flushWrites(false)
{ }
MsgPackStream::MsgPackStream(QByteArray *a, QIODevice::OpenMode mode) :
owndev(true), q_status(Ok)
owndev(true), q_status(Ok), flushWrites(false)
{
QBuffer *buf = new QBuffer(a);
buf->open(mode);
@ -40,7 +40,7 @@ MsgPackStream::MsgPackStream(QByteArray *a, QIODevice::OpenMode mode) :
}
MsgPackStream::MsgPackStream(const QByteArray &a) :
owndev(true), q_status(Ok)
owndev(true), q_status(Ok), flushWrites(false)
{
QBuffer *buf = new QBuffer();
buf->setData(a);
@ -87,6 +87,16 @@ void MsgPackStream::setStatus(Status status)
q_status = status;
}
void MsgPackStream::setFlushWrites(bool flush)
{
flushWrites = flush;
}
bool MsgPackStream::willFlushWrites()
{
return flushWrites;
}
MsgPackStream &MsgPackStream::operator>>(bool &b)
{
CHECK_STREAM_PRECOND(*this)
@ -503,6 +513,16 @@ bool MsgPackStream::writeBytes(const char *data, uint len)
setStatus(WriteFailed);
return false;
}
/* Apparently on Windows, the buffer size for named pipes is 0, and
* any data that is written before the remote end reads it is
* dropped (!!) without error (see https://bugreports.qt.io/browse/QTBUG-18385).
* We must be very sure that the data has been written before we try
* another write. This degrades performance in other cases, so callers
* must enable this behavior explicitly.
*/
if (this->flushWrites) {
dev->waitForBytesWritten(-1);
}
/* Increment the write pointer and the total byte count. */
data += thisWrite;

View File

@ -26,6 +26,8 @@ public:
Status status() const;
void resetStatus();
void setStatus(Status status);
void setFlushWrites(bool flushWrites);
bool willFlushWrites();
MsgPackStream &operator>>(bool &b);
MsgPackStream &operator>>(quint8 &u8);
@ -60,6 +62,7 @@ private:
QIODevice *dev;
bool owndev;
Status q_status;
bool flushWrites;
bool unpack_longlong(qint64 &i64);
bool unpack_ulonglong(quint64 &u64);