ONE - On-device Neural Engine
Loading...
Searching...
No Matches
grpc.h
Go to the documentation of this file.
1/*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef FLATBUFFERS_GRPC_H_
18#define FLATBUFFERS_GRPC_H_
19
20// Helper functionality to glue FlatBuffers and GRPC.
21
23#include "grpcpp/support/byte_buffer.h"
24#include "grpcpp/support/slice.h"
25
26namespace flatbuffers {
27namespace grpc {
28
29// Message is a typed wrapper around a buffer that manages the underlying
30// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
31// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
32// is refcounted and ownership is be managed automatically.
33template<class T> class Message {
34 public:
36
37 Message(::grpc::Slice slice) : slice_(slice) {}
38
39 Message &operator=(const Message &other) = delete;
40
41 Message(Message &&other) = default;
42
43 Message(const Message &other) = delete;
44
45 Message &operator=(Message &&other) = default;
46
47 const uint8_t *mutable_data() const { return slice_.begin(); }
48
49 const uint8_t *data() const { return slice_.begin(); }
50
51 size_t size() const { return slice_.size(); }
52
53 bool Verify() const {
54 Verifier verifier(data(), size());
55 return verifier.VerifyBuffer<T>(nullptr);
56 }
57
58 T *GetMutableRoot() { return flatbuffers::GetMutableRoot<T>(mutable_data()); }
59
60 const T *GetRoot() const { return flatbuffers::GetRoot<T>(data()); }
61
62 // This is only intended for serializer use, or if you know what you're doing
63 const ::grpc::Slice &BorrowSlice() const { return slice_; }
64
65 private:
66 ::grpc::Slice slice_;
67};
68
69class MessageBuilder;
70
71// SliceAllocator is a gRPC-specific allocator that uses the `grpc_slice`
72// refcounted slices to manage memory ownership. This makes it easy and
73// efficient to transfer buffers to gRPC.
74class SliceAllocator : public Allocator {
75 public:
77
78 SliceAllocator(const SliceAllocator &other) = delete;
79 SliceAllocator &operator=(const SliceAllocator &other) = delete;
80
82 // default-construct and swap idiom
83 swap(other);
84 }
85
87 // move-construct and swap idiom
88 SliceAllocator temp(std::move(other));
89 swap(temp);
90 return *this;
91 }
92
93 void swap(SliceAllocator &other) {
94 using std::swap;
95 swap(slice_, other.slice_);
96 }
97
98 virtual ~SliceAllocator() {}
99
100 virtual uint8_t *allocate(size_t size) override {
101 FLATBUFFERS_ASSERT(slice_.size() == 0);
102 slice_ = ::grpc::Slice(size);
103 return const_cast<uint8_t *>(slice_.begin());
104 }
105
106 virtual void deallocate(uint8_t *p, size_t size) override {
107 FLATBUFFERS_ASSERT(p == slice_.begin());
108 FLATBUFFERS_ASSERT(size == slice_.size());
109 slice_ = ::grpc::Slice();
110 }
111
112 virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
113 size_t new_size, size_t in_use_back,
114 size_t in_use_front) override {
115 FLATBUFFERS_ASSERT(old_p == slice_.begin());
116 FLATBUFFERS_ASSERT(old_size == slice_.size());
117 FLATBUFFERS_ASSERT(new_size > old_size);
118 ::grpc::Slice old_slice = slice_;
119 ::grpc::Slice new_slice = ::grpc::Slice(new_size);
120 uint8_t *new_p = const_cast<uint8_t *>(new_slice.begin());
121 memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
122 in_use_front);
123 slice_ = new_slice;
124 return new_p;
125 }
126
127 private:
128 ::grpc::Slice &get_slice(uint8_t *p, size_t size) {
129 FLATBUFFERS_ASSERT(p == slice_.begin());
130 FLATBUFFERS_ASSERT(size == slice_.size());
131 return slice_;
132 }
133
134 ::grpc::Slice slice_;
135
136 friend class MessageBuilder;
137};
138
139// SliceAllocatorMember is a hack to ensure that the MessageBuilder's
140// slice_allocator_ member is constructed before the FlatBufferBuilder, since
141// the allocator is used in the FlatBufferBuilder ctor.
142namespace detail {
143struct SliceAllocatorMember {
144 SliceAllocator slice_allocator_;
145};
146} // namespace detail
147
148// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
149// to allocate gRPC buffers.
150class MessageBuilder : private detail::SliceAllocatorMember,
151 public FlatBufferBuilder {
152 public:
153 explicit MessageBuilder(uoffset_t initial_size = 1024)
154 : FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
155
156 MessageBuilder(const MessageBuilder &other) = delete;
157 MessageBuilder &operator=(const MessageBuilder &other) = delete;
158
160 : FlatBufferBuilder(1024, &slice_allocator_, false) {
161 // Default construct and swap idiom.
162 Swap(other);
163 }
164
167 void (*dealloc)(void *,
168 size_t) = &DefaultAllocator::dealloc)
169 : FlatBufferBuilder(1024, &slice_allocator_, false) {
170 src.Swap(*this);
171 src.SwapBufAllocator(*this);
172 if (buf_.capacity()) {
173 uint8_t *buf = buf_.scratch_data(); // pointer to memory
174 size_t capacity = buf_.capacity(); // size of memory
175 slice_allocator_.slice_ = ::grpc::Slice(buf, capacity, dealloc);
176 } else {
177 slice_allocator_.slice_ = ::grpc::Slice();
178 }
179 }
180
185 // Move construct a temporary and swap
186 MessageBuilder temp(std::move(src));
187 Swap(temp);
188 return *this;
189 }
190
192 // Move construct a temporary and swap
193 MessageBuilder temp(std::move(other));
194 Swap(temp);
195 return *this;
196 }
197
198 void Swap(MessageBuilder &other) {
199 slice_allocator_.swap(other.slice_allocator_);
201 // After swapping the FlatBufferBuilder, we swap back the allocator, which
202 // restores the original allocator back in place. This is necessary because
203 // MessageBuilder's allocator is its own member (SliceAllocatorMember). The
204 // allocator passed to FlatBufferBuilder::vector_downward must point to this
205 // member.
206 buf_.swap_allocator(other.buf_);
207 }
208
209 // Releases the ownership of the buffer pointer.
210 // Returns the size, offset, and the original grpc_slice that
211 // allocated the buffer. Also see grpc_slice_unref().
212 uint8_t *ReleaseRaw(size_t &size, size_t &offset, ::grpc::Slice &slice) {
214 slice = slice_allocator_.slice_;
215 slice_allocator_.slice_ = ::grpc::Slice();
216 return buf;
217 }
218
220
221 // GetMessage extracts the subslice of the buffer corresponding to the
222 // flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
223 // ownership.
224 template<class T> Message<T> GetMessage() {
225 auto buf_data = buf_.scratch_data(); // pointer to memory
226 auto buf_size = buf_.capacity(); // size of memory
227 auto msg_data = buf_.data(); // pointer to msg
228 auto msg_size = buf_.size(); // size of msg
229 // Do some sanity checks on data/size
230 FLATBUFFERS_ASSERT(msg_data);
231 FLATBUFFERS_ASSERT(msg_size);
232 FLATBUFFERS_ASSERT(msg_data >= buf_data);
233 FLATBUFFERS_ASSERT(msg_data + msg_size <= buf_data + buf_size);
234 // Calculate offsets from the buffer start
235 auto begin = msg_data - buf_data;
236 auto end = begin + msg_size;
237 // Get the slice we are working with (no refcount change)
238 ::grpc::Slice slice = slice_allocator_.get_slice(buf_data, buf_size);
239 // Extract a subslice of the existing slice (increment refcount)
240 ::grpc::Slice subslice = slice.sub(begin, end);
241 // Wrap the subslice in a `Message<T>`, but don't increment refcount
242 Message<T> msg(subslice);
243 return msg;
244 }
245
246 template<class T> Message<T> ReleaseMessage() {
247 Message<T> msg = GetMessage<T>();
248 Reset();
249 return msg;
250 }
251
252 private:
253 // SliceAllocator slice_allocator_; // part of SliceAllocatorMember
254};
255
256} // namespace grpc
257} // namespace flatbuffers
258
259namespace grpc {
260
261template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
262 public:
263 static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
264 ByteBuffer *buffer, bool *own_buffer) {
265 // Package the single slice into a `ByteBuffer`,
266 // incrementing the refcount in the process.
267 *buffer = ByteBuffer(&msg.BorrowSlice(), 1);
268 *own_buffer = true;
269 return grpc::Status::OK;
270 }
271
272 // Deserialize by pulling the
273 static grpc::Status Deserialize(ByteBuffer *buf,
275 Slice slice;
276 if (!buf->TrySingleSlice(&slice).ok()) {
277 if (!buf->DumpToSingleSlice(&slice).ok()) {
278 buf->Clear();
279 return ::grpc::Status(::grpc::StatusCode::INTERNAL, "No payload");
280 }
281 }
282 *msg = flatbuffers::grpc::Message<T>(slice);
283 buf->Clear();
284#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
285 return ::grpc::Status::OK;
286#else
287 if (msg->Verify()) {
288 return ::grpc::Status::OK;
289 } else {
290 return ::grpc::Status(::grpc::StatusCode::INTERNAL,
291 "Message verification failed");
292 }
293#endif
294 }
295};
296
297} // namespace grpc
298
299#endif // FLATBUFFERS_GRPC_H_
#define FLATBUFFERS_ASSERT
Definition base.h:21
void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p, size_t new_size, size_t in_use_back, size_t in_use_front)
Definition allocator.h:57
static void dealloc(void *p, size_t)
uint8_t * ReleaseRaw(size_t &size, size_t &offset)
Get the released pointer to the serialized buffer.
void Swap(FlatBufferBuilderImpl &other)
MessageBuilder & operator=(FlatBufferBuilder &&src)
Definition grpc.h:184
void Swap(MessageBuilder &other)
Definition grpc.h:198
MessageBuilder(const MessageBuilder &other)=delete
uint8_t * ReleaseRaw(size_t &size, size_t &offset, ::grpc::Slice &slice)
Definition grpc.h:212
MessageBuilder(MessageBuilder &&other)
Definition grpc.h:159
Message< T > ReleaseMessage()
Definition grpc.h:246
MessageBuilder & operator=(MessageBuilder &&other)
Definition grpc.h:191
MessageBuilder & operator=(const MessageBuilder &other)=delete
MessageBuilder(uoffset_t initial_size=1024)
Definition grpc.h:153
MessageBuilder(FlatBufferBuilder &&src, void(*dealloc)(void *, size_t)=&DefaultAllocator::dealloc)
Create a MessageBuilder from a FlatBufferBuilder.
Definition grpc.h:166
const uint8_t * mutable_data() const
Definition grpc.h:47
const ::grpc::Slice & BorrowSlice() const
Definition grpc.h:63
Message(::grpc::Slice slice)
Definition grpc.h:37
const uint8_t * data() const
Definition grpc.h:49
Message(Message &&other)=default
size_t size() const
Definition grpc.h:51
Message(const Message &other)=delete
Message & operator=(Message &&other)=default
bool Verify() const
Definition grpc.h:53
const T * GetRoot() const
Definition grpc.h:60
Message & operator=(const Message &other)=delete
SliceAllocator & operator=(SliceAllocator &&other)
Definition grpc.h:86
virtual void deallocate(uint8_t *p, size_t size) override
Definition grpc.h:106
SliceAllocator & operator=(const SliceAllocator &other)=delete
virtual uint8_t * allocate(size_t size) override
Definition grpc.h:100
SliceAllocator(SliceAllocator &&other)
Definition grpc.h:81
virtual uint8_t * reallocate_downward(uint8_t *old_p, size_t old_size, size_t new_size, size_t in_use_back, size_t in_use_front) override
Definition grpc.h:112
SliceAllocator(const SliceAllocator &other)=delete
void swap(SliceAllocator &other)
Definition grpc.h:93
void swap_allocator(vector_downward &other)
__global uchar * offset(const Image *img, int x, int y)
Definition helpers.h:540
Definition grpc.h:259
int32_t size[5]
Definition Slice.cpp:35
int32_t begin[5]
Definition Slice.cpp:33
Configuration p