Commit fb645211 authored by TJ Yin's avatar TJ Yin Committed by Facebook GitHub Bot

Make RWCursor constructible from IOBufQueue

Summary: This diff added conversion from `IOBufQueue` and `QueueAppender` to `RWCursor`. It's safe to use `RWCursor` to mutate the their underlying `IOBuf` since the structure of `IOBuf` won't changed. It's worth noting appending data to `IOBufQueue` will invalidate RWCursor (just like iterator).

Reviewed By: yfeldblum

Differential Revision: D27257697

fbshipit-source-id: 17887d656a6095afe1c6882426457b9e75a66c84
parent 7df2d7e5
...@@ -897,6 +897,9 @@ class RWCursor : public detail::CursorBase<RWCursor<access>, IOBuf>, ...@@ -897,6 +897,9 @@ class RWCursor : public detail::CursorBase<RWCursor<access>, IOBuf>,
explicit RWCursor(IOBuf* buf) explicit RWCursor(IOBuf* buf)
: detail::CursorBase<RWCursor<access>, IOBuf>(buf), maybeShared_(true) {} : detail::CursorBase<RWCursor<access>, IOBuf>(buf), maybeShared_(true) {}
explicit RWCursor(IOBufQueue& queue)
: RWCursor((queue.flushCache(), queue.head_.get())) {}
template <class OtherDerived, class OtherBuf> template <class OtherDerived, class OtherBuf>
explicit RWCursor(const detail::CursorBase<OtherDerived, OtherBuf>& cursor) explicit RWCursor(const detail::CursorBase<OtherDerived, OtherBuf>& cursor)
: detail::CursorBase<RWCursor<access>, IOBuf>(cursor), : detail::CursorBase<RWCursor<access>, IOBuf>(cursor),
...@@ -1240,6 +1243,11 @@ class QueueAppender : public detail::Writable<QueueAppender> { ...@@ -1240,6 +1243,11 @@ class QueueAppender : public detail::Writable<QueueAppender> {
queueCache_.queue()->append(buf, true); queueCache_.queue()->append(buf, true);
} }
template <CursorAccess access>
explicit operator RWCursor<access>() {
return RWCursor<access>(*queueCache_.queue());
}
private: private:
folly::IOBufQueue::WritableRangeCache queueCache_{nullptr}; folly::IOBufQueue::WritableRangeCache queueCache_{nullptr};
size_t growth_{0}; size_t growth_{0};
......
...@@ -24,6 +24,12 @@ ...@@ -24,6 +24,12 @@
namespace folly { namespace folly {
namespace io {
enum class CursorAccess;
template <CursorAccess>
class RWCursor;
} // namespace io
/** /**
* An IOBufQueue encapsulates a chain of IOBufs and provides * An IOBufQueue encapsulates a chain of IOBufs and provides
* convenience functions to append data to the back of the chain * convenience functions to append data to the back of the chain
...@@ -34,6 +40,9 @@ namespace folly { ...@@ -34,6 +40,9 @@ namespace folly {
*/ */
class IOBufQueue { class IOBufQueue {
private: private:
template <io::CursorAccess>
friend class io::RWCursor;
/** /**
* This guard should be taken by any method that intends to do any changes * This guard should be taken by any method that intends to do any changes
* to in data_ (e.g. appending to it). * to in data_ (e.g. appending to it).
......
...@@ -615,6 +615,33 @@ TEST(IOBuf, QueueAppenderInsertClone) { ...@@ -615,6 +615,33 @@ TEST(IOBuf, QueueAppenderInsertClone) {
EXPECT_EQ(x, queue.front()->next()->data()[0]); EXPECT_EQ(x, queue.front()->next()->data()[0]);
} }
TEST(IOBuf, QueueAppenderRWCursor) {
folly::IOBufQueue queue;
QueueAppender app(&queue, 100);
const size_t n = 1024 / sizeof(uint32_t);
for (size_t m = 0; m < n; m++) {
for (uint32_t i = 0; i < n; ++i) {
app.writeBE<uint32_t>(0);
}
RWPrivateCursor rw(app);
// Advance cursor to skip data that's already overwritten
rw += m * n * sizeof(uint32_t);
// Overwrite the data
for (uint32_t i = 0; i < n; ++i) {
rw.writeBE<uint32_t>(i + m * n);
}
}
Cursor cursor(queue.front());
for (uint32_t i = 0; i < n * n; ++i) {
EXPECT_EQ(i, cursor.readBE<uint32_t>());
}
}
TEST(IOBuf, CursorOperators) { TEST(IOBuf, CursorOperators) {
// Test operators on a single-item chain // Test operators on a single-item chain
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment