From a8eaaa0c3efac81262d956a71738c7ae30532671 Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Tue, 12 Jun 2018 12:30:36 +0200 Subject: If moving a non-owned buffer make sure to copy the buffer. --- .../src/tests/objects/nbostream/nbostream_test.cpp | 39 ++++++++++++++++++++++ vespalib/src/vespa/vespalib/objects/nbostream.cpp | 28 ++++++++++++++++ vespalib/src/vespa/vespalib/objects/nbostream.h | 6 ++-- 3 files changed, 70 insertions(+), 3 deletions(-) (limited to 'vespalib') diff --git a/vespalib/src/tests/objects/nbostream/nbostream_test.cpp b/vespalib/src/tests/objects/nbostream/nbostream_test.cpp index 8b9ccb8a848..ab7265dfd69 100644 --- a/vespalib/src/tests/objects/nbostream/nbostream_test.cpp +++ b/vespalib/src/tests/objects/nbostream/nbostream_test.cpp @@ -7,6 +7,7 @@ #include using vespalib::nbostream; +using vespalib::alloc::Alloc; using ExpBuffer = std::vector; namespace std @@ -60,6 +61,44 @@ struct Fixture } }; +TEST("test that move of owned buffer does not copy") { + Alloc buf = Alloc::allocHeap(1000); + const void * ptr = buf.get(); + nbostream os(std::move(buf), 0); + os << static_cast(0x567); + EXPECT_EQUAL(ptr, os.peek()); + EXPECT_EQUAL(8ul, os.size()); + nbostream moved(std::move(os)); + EXPECT_TRUE(nullptr == os.peek()); + EXPECT_EQUAL(0ul, os.size()); + EXPECT_EQUAL(ptr, moved.peek()); + EXPECT_EQUAL(8ul, moved.size()); + long tmp(0); + moved >> tmp; + EXPECT_EQUAL(0x567l, tmp); +} + +TEST("test that move of non-owned buffer does copy") { + Alloc buf = Alloc::allocHeap(1000); + const void * ptr = buf.get(); + nbostream os(std::move(buf), 0); + os << static_cast(0x567); + EXPECT_EQUAL(ptr, os.peek()); + EXPECT_EQUAL(8ul, os.size()); + nbostream refering(os.peek(), os.size()); + EXPECT_EQUAL(ptr, os.peek()); + EXPECT_EQUAL(8ul, os.size()); + EXPECT_EQUAL(ptr, refering.peek()); + EXPECT_EQUAL(8ul, refering.size()); + nbostream moved(std::move(refering)); + EXPECT_TRUE(nullptr == refering.peek()); + EXPECT_EQUAL(0ul, refering.size()); + EXPECT_TRUE(ptr != moved.peek()); + EXPECT_EQUAL(8ul, moved.size()); + long tmp(0); + moved >> tmp; + EXPECT_EQUAL(0x567l, tmp); +} TEST_F("test serializing 64-bit signed integers", Fixture) { diff --git a/vespalib/src/vespa/vespalib/objects/nbostream.cpp b/vespalib/src/vespa/vespalib/objects/nbostream.cpp index ea9684efe01..871c88b5465 100644 --- a/vespalib/src/vespa/vespalib/objects/nbostream.cpp +++ b/vespalib/src/vespa/vespalib/objects/nbostream.cpp @@ -63,6 +63,33 @@ nbostream::nbostream(const nbostream & rhs) : memcpy(&_wbuf[0], &rhs._rbuf[rhs._rp], _wp); } +nbostream::nbostream(nbostream && rhs) noexcept + : _wbuf(std::move(rhs._wbuf)), + _rbuf(rhs._rbuf), + _rp(rhs._rp), + _wp(rhs._wp), + _state(rhs._state), + _longLivedBuffer(rhs._longLivedBuffer) +{ + rhs._rp = 0; + rhs._wp = 0; + rhs._rbuf = ConstBufferRef(); + if (!_longLivedBuffer && (_wbuf.capacity() == 0)) { + _wbuf.resize(roundUp2inN(_rbuf.size())); + memcpy(&_wbuf[0], &_rbuf[_rp], size()); + _wp = size(); + _rp = 0; + _rbuf = ConstBufferRef(&_wbuf[0], _wbuf.capacity()); + } +} + +nbostream & +nbostream::operator = (nbostream && rhs) noexcept { + nbostream tmp(std::move(rhs)); + swap(tmp); + return *this; +} + nbostream & nbostream::operator = (const nbostream & rhs) { if (this != &rhs) { @@ -134,6 +161,7 @@ void nbostream::swap(nbostream & os) std::swap(_state, os._state); _wbuf.swap(os._wbuf); std::swap(_rbuf, os._rbuf); + std::swap(_longLivedBuffer, os._longLivedBuffer); } } diff --git a/vespalib/src/vespa/vespalib/objects/nbostream.h b/vespalib/src/vespa/vespalib/objects/nbostream.h index 70a590f79d1..b51fff1b7cc 100644 --- a/vespalib/src/vespa/vespalib/objects/nbostream.h +++ b/vespalib/src/vespa/vespalib/objects/nbostream.h @@ -28,11 +28,11 @@ public: nbostream(const void * buf, size_t sz); nbostream(Alloc && buf, size_t sz); nbostream(const nbostream & rhs); - nbostream(nbostream && rhs) noexcept = default; + nbostream(nbostream && rhs) noexcept; ~nbostream(); nbostream & operator = (const nbostream & rhs); - nbostream & operator = (nbostream && rhs) noexcept = default; + nbostream & operator = (nbostream && rhs) noexcept; nbostream & operator << (double v) { double n(nbo::n2h(v)); write8(&n); return *this; } nbostream & operator >> (double & v) { double n; read8(&n); v = nbo::n2h(n); return *this; } @@ -228,7 +228,7 @@ public: size_t _rp; size_t _wp; State _state; - const bool _longLivedBuffer; + bool _longLivedBuffer; }; class nbostream_longlivedbuf : public nbostream { -- cgit v1.2.3