Adding stack allocated protobuf arena class.
Change-Id: I1ee15b79fdb54b787b94b3d424e4df36c82ad849
diff --git a/aos/protobuf/stack_arena.h b/aos/protobuf/stack_arena.h
new file mode 100644
index 0000000..28c933c
--- /dev/null
+++ b/aos/protobuf/stack_arena.h
@@ -0,0 +1,52 @@
+#ifndef AOS_PROTOBUF_STACK_ARENA_H_
+#define AOS_PROTOBUF_STACK_ARENA_H_
+#include "google/protobuf/arena.h"
+
+namespace aos {
+namespace protobuf {
+
+void* FatalArenaBlockAlloc(size_t);
+
+void FatalArenaBlockDealloc(void*, size_t);
+
+// This class manages a protobuf arena which uses an internal buffer
+// (allocated as part of the object) of size buffer_size.
+//
+// Protos allocated from this arena must not use more than buffer_size
+// worth of data.
+//
+// Also worth noting is that sizeof(google::protobuf::Arena::Block)
+// is used up out of the buffer for internal protobuf related usage, so
+// overallocate accordingly.
+template <size_t buffer_size>
+class StackProtoArena {
+ public:
+ StackProtoArena() :
+ arena_(GetArenaOptions(&data_[0])) {}
+
+ google::protobuf::Arena* arena() { return &arena_; }
+
+ // For convienence:
+ template <typename T>
+ T* CreateMessage() {
+ return google::protobuf::Arena::CreateMessage<T>(&arena_);
+ }
+ private:
+ static google::protobuf::ArenaOptions GetArenaOptions(char* data) {
+ // Expecting RVO to kick in.
+ google::protobuf::ArenaOptions options;
+ options.initial_block = data;
+ options.initial_block_size = buffer_size;
+ options.block_alloc = &FatalArenaBlockAlloc;
+ options.block_dealloc = FatalArenaBlockDealloc;
+ return options;
+ }
+
+ char data_[buffer_size];
+ google::protobuf::Arena arena_;
+};
+
+} // namespace protobuf
+} // namespace aos
+
+#endif // AOS_PROTOBUF_STACK_ARENA_H_