summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@oath.com>2018-06-12 12:30:36 +0200
committerHenning Baldersheim <balder@oath.com>2018-06-12 13:05:27 +0200
commita8eaaa0c3efac81262d956a71738c7ae30532671 (patch)
tree03793ec500b24897b6cc150ba7ebea375398c306
parentacb2bb30339e55acd44985c03cd91ce29c4e3112 (diff)
If moving a non-owned buffer make sure to copy the buffer.
-rw-r--r--vespalib/src/tests/objects/nbostream/nbostream_test.cpp39
-rw-r--r--vespalib/src/vespa/vespalib/objects/nbostream.cpp28
-rw-r--r--vespalib/src/vespa/vespalib/objects/nbostream.h6
3 files changed, 70 insertions, 3 deletions
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 <ostream>
using vespalib::nbostream;
+using vespalib::alloc::Alloc;
using ExpBuffer = std::vector<uint8_t>;
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<long>(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<long>(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 {