From 89b0364cded81457eaa264c1634af5d082da3c21 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Mon, 11 Jul 2016 14:06:49 +0300 Subject: QRingBuffer: avoid reallocations of the data Since its initial implementation, QRingBuffer had the following fragilities in the architecture: - it does not guarantee validity of the pointers, if new data will be appended. As an example, passing an address of the QRingBuffer chunk as a parameter to the WriteFileEx() function on Windows requires the stability of the pointer. So, we can't add new data to the QRingBuffer until the overlapped operation completed (related issues were fixed for QWindowsPipeWriter and QSerialPort in 5.6 branch by introducing an intermediate byte array); - inefficient reallocations in reserve(), if a shared chunk was inserted in the queue (we can get a reallocation in the place where we don't expect it: char *writePtr = buffers.last().data() + tail; <- line #133 ). Proposed solution is to avoid reallocation by allocating a new block instead. That was accomplished by introducing a QRingChunk class which operates on a fixed byte array and implements head/tail pointers strategy for each individual buffer in the queue. So, QRingBuffer is no longer dependent on QByteArray's internal shrink/growth algorithms. Change-Id: I05abab0ad78e22e4815a196037dfc6eff85325d1 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'tests/auto/corelib/tools/qringbuffer') diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp index deee7171b1..e355a7fcfb 100644 --- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp +++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp @@ -48,6 +48,7 @@ private slots: void reserveAndReadInPacketMode(); void reserveFrontAndRead(); void chop(); + void readPointerValidity(); void ungetChar(); void indexOf(); void appendAndRead(); @@ -303,6 +304,21 @@ void tst_QRingBuffer::chop() QVERIFY(memcmp(ringBuffer.readPointer(), "0123", 4) == 0); } +void tst_QRingBuffer::readPointerValidity() +{ + QRingBuffer ringBuffer(16); + QByteArray ba("Hello world!"); + + ringBuffer.append(ba); + const char *ptr = ringBuffer.readPointer(); + ba.clear(); + ringBuffer.reserve(32); + QVERIFY(ptr == ringBuffer.readPointer()); + ringBuffer.reserveFront(32); + qint64 dummy; + QVERIFY(ptr == ringBuffer.readPointerAtPosition(32, dummy)); +} + void tst_QRingBuffer::ungetChar() { QRingBuffer ringBuffer(16); -- cgit v1.2.3