SliceAllocator is a gRPC-specific allocator that uses the `grpc_slice` refcounted slices to manage memory ownership. This makes it easy and efficient to transfer buffers to gRPC.
| 82 | // refcounted slices to manage memory ownership. This makes it easy and |
| 83 | // efficient to transfer buffers to gRPC. |
| 84 | class SliceAllocator : public Allocator { |
| 85 | public: |
| 86 | SliceAllocator() : slice_(grpc_empty_slice()) {} |
| 87 | |
| 88 | SliceAllocator(const SliceAllocator &other) = delete; |
| 89 | SliceAllocator &operator=(const SliceAllocator &other) = delete; |
| 90 | |
| 91 | SliceAllocator(SliceAllocator &&other) : slice_(grpc_empty_slice()) { |
| 92 | // default-construct and swap idiom |
| 93 | swap(other); |
| 94 | } |
| 95 | |
| 96 | SliceAllocator &operator=(SliceAllocator &&other) { |
| 97 | // move-construct and swap idiom |
| 98 | SliceAllocator temp(std::move(other)); |
| 99 | swap(temp); |
| 100 | return *this; |
| 101 | } |
| 102 | |
| 103 | void swap(SliceAllocator &other) { |
| 104 | using std::swap; |
| 105 | swap(slice_, other.slice_); |
| 106 | } |
| 107 | |
| 108 | virtual ~SliceAllocator() { grpc_slice_unref(slice_); } |
| 109 | |
| 110 | virtual uint8_t *allocate(size_t size) override { |
| 111 | FLATBUFFERS_ASSERT(GRPC_SLICE_IS_EMPTY(slice_)); |
| 112 | slice_ = grpc_slice_malloc(size); |
| 113 | return GRPC_SLICE_START_PTR(slice_); |
| 114 | } |
| 115 | |
| 116 | virtual void deallocate(uint8_t *p, size_t size) override { |
| 117 | FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_)); |
| 118 | FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_)); |
| 119 | grpc_slice_unref(slice_); |
| 120 | slice_ = grpc_empty_slice(); |
| 121 | } |
| 122 | |
| 123 | virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size, |
| 124 | size_t new_size, size_t in_use_back, |
| 125 | size_t in_use_front) override { |
| 126 | FLATBUFFERS_ASSERT(old_p == GRPC_SLICE_START_PTR(slice_)); |
| 127 | FLATBUFFERS_ASSERT(old_size == GRPC_SLICE_LENGTH(slice_)); |
| 128 | FLATBUFFERS_ASSERT(new_size > old_size); |
| 129 | grpc_slice old_slice = slice_; |
| 130 | grpc_slice new_slice = grpc_slice_malloc(new_size); |
| 131 | uint8_t *new_p = GRPC_SLICE_START_PTR(new_slice); |
| 132 | memcpy_downward(old_p, old_size, new_p, new_size, in_use_back, |
| 133 | in_use_front); |
| 134 | slice_ = new_slice; |
| 135 | grpc_slice_unref(old_slice); |
| 136 | return new_p; |
| 137 | } |
| 138 | |
| 139 | private: |
| 140 | grpc_slice &get_slice(uint8_t *p, size_t size) { |
| 141 | FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_)); |