Efficient Conversion of a FlatBufferBuilder to a MessageBuilder (#4980)

* Efficient conversion of FlatBufferBuilder to grpc::MessageBuilder

* Added a variety of tests to validate correctness of the MessageBuilder move operations.
Disable MessageBuilder half-n-half tests on MacOS.

* Fix failing Android build

* Generalized the MessageBuilder move constructor to accept a deallocator
This commit is contained in:
Sumant Tambe
2018-10-18 10:32:59 -07:00
committed by Wouter van Oortmerssen
parent ad8b1e5dbd
commit 802639e40d
6 changed files with 441 additions and 220 deletions

View File

@@ -425,6 +425,10 @@ class DefaultAllocator : public Allocator {
void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
delete[] p;
}
static void dealloc(void *p, size_t) {
delete[] static_cast<uint8_t *>(p);
}
};
// These functions allow for a null allocator to mean use the default allocator,
@@ -549,7 +553,7 @@ class DetachedBuffer {
#endif // !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
protected:
protected:
Allocator *allocator_;
bool own_allocator_;
uint8_t *buf_;
@@ -986,7 +990,7 @@ class FlatBufferBuilder {
/// `FlatBuffer` starts.
/// @return A raw pointer to the start of the memory block containing
/// the serialized `FlatBuffer`.
/// @remark If the allocator is owned, it gets deleted during this call.
/// @remark If the allocator is owned, it gets deleted when the destructor is called..
uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
Finished();
return buf_.release_raw(size, offset);
@@ -1759,7 +1763,12 @@ class FlatBufferBuilder {
Finish(root.o, file_identifier, true);
}
protected:
void SwapBufAllocator(FlatBufferBuilder &other) {
buf_.swap_allocator(other.buf_);
}
protected:
// You shouldn't really be copying instances of this class.
FlatBufferBuilder(const FlatBufferBuilder &);
FlatBufferBuilder &operator=(const FlatBufferBuilder &);

View File

@@ -164,7 +164,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
public FlatBufferBuilder {
public:
explicit MessageBuilder(uoffset_t initial_size = 1024)
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
MessageBuilder(const MessageBuilder &other) = delete;
MessageBuilder &operator=(const MessageBuilder &other) = delete;
@@ -175,6 +175,30 @@ class MessageBuilder : private detail::SliceAllocatorMember,
Swap(other);
}
/// Create a MessageBuilder from a FlatBufferBuilder.
explicit MessageBuilder(FlatBufferBuilder &&src, void (*dealloc)(void*, size_t) = &DefaultAllocator::dealloc)
: FlatBufferBuilder(1024, &slice_allocator_, false) {
src.Swap(*this);
src.SwapBufAllocator(*this);
if (buf_.capacity()) {
uint8_t *buf = buf_.scratch_data(); // pointer to memory
size_t capacity = buf_.capacity(); // size of memory
slice_allocator_.slice_ = grpc_slice_new_with_len(buf, capacity, dealloc);
}
else {
slice_allocator_.slice_ = grpc_empty_slice();
}
}
/// Move-assign a FlatBufferBuilder to a MessageBuilder.
/// Only FlatBufferBuilder with default allocator (basically, nullptr) is supported.
MessageBuilder &operator=(FlatBufferBuilder &&src) {
// Move construct a temporary and swap
MessageBuilder temp(std::move(src));
Swap(temp);
return *this;
}
MessageBuilder &operator=(MessageBuilder &&other) {
// Move construct a temporary and swap
MessageBuilder temp(std::move(other));