From 53a897731e23320e67602d3d4c56e09caffb98ca Mon Sep 17 00:00:00 2001 From: rmawatson Date: Fri, 1 Dec 2017 18:15:41 +0100 Subject: [PATCH] this is allow custom allocator for obj-api structs/tables. (#4520) added "native_custom_alloc" attribute to tables/structs, eg. table parent_table( native_custom_alloc:"custom_alloc_name" ) { ... } with a custom allocator defined as template class custom_alloc_name : public std::allocator { public: typedef T* pointer; template struct rebind { typedef custom_alloc_name other; }; pointer allocate(const std::size_t n) { return ....; } void deallocate(T* ptr, std::size_t n) { ... } custom_alloc_name() throw() {} template custom_alloc_name(const custom_alloc_name&) throw() {} }; }; --- docs/source/CppUsage.md | 39 ++++++++++++++++++ include/flatbuffers/flatbuffers.h | 8 ++-- include/flatbuffers/idl.h | 1 + src/idl_gen_cpp.cpp | 20 ++++++++- src/idl_parser.cpp | 4 ++ tests/monster_test.bfbs | Bin 5400 -> 5520 bytes .../namespace_test2_generated.ts | 20 ++++----- 7 files changed, 77 insertions(+), 15 deletions(-) diff --git a/docs/source/CppUsage.md b/docs/source/CppUsage.md index 2ded61103..e858e0a34 100644 --- a/docs/source/CppUsage.md +++ b/docs/source/CppUsage.md @@ -126,6 +126,45 @@ The following attributes are specific to the object-based API code generation: "native_inline", the value specified with this attribute will be included verbatim in the class constructor initializer list for this member. +- `native_custom_alloc`:"custom_allocator" (on a table or struct): When using the + object-based API all generated NativeTables that are allocated when unpacking + your flatbuffer will use "custom allocator". The allocator is also used by + any std::vector that appears in a table defined with `native_custom_alloc`. + This can be used to provide allocation from a pool for example, for faster + unpacking when using the object-based API. + + Minimal Example: + + schema: + + table mytable(native_custom_alloc:"custom_allocator") { + ... + } + + with custom_allocator defined before flatbuffers.h is included, as: + + template struct custom_allocator : public std::allocator { + + typedef T *pointer; + + template + struct rebind { + typedef custom_allocator other; + }; + + pointer allocate(const std::size_t n) { + return std::allocator::allocate(n); + } + + void deallocate(T* ptr, std::size_t n) { + return std::allocator::deallocate(ptr,n); + } + + custom_allocator() throw() {} + template + custom_allocator(const custom_allocator&) throw() {} + }; + - `native_type`' "type" (on a struct): In some cases, a more optimal C++ data type exists for a given struct. For example, the following schema: diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 3b56ba491..aa5df859f 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -656,10 +656,10 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) { return static_cast((field_id + fixed_fields) * sizeof(voffset_t)); } -template const T* data(const std::vector &v) { +template const T* data(const std::vector &v) { return v.empty() ? nullptr : &v.front(); } -template T* data(std::vector &v) { +template T* data(std::vector &v) { return v.empty() ? nullptr : &v.front(); } @@ -1283,8 +1283,8 @@ class FlatBufferBuilder /// serialize into the buffer as a `vector`. /// @return Returns a typed `Offset` into the serialized data indicating /// where the vector is stored. - template Offset> CreateVectorOfStructs( - const std::vector &v) { + template Offset> CreateVectorOfStructs( + const std::vector &v) { return CreateVectorOfStructs(data(v), v.size()); } diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index c0408de63..d06b5a429 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -526,6 +526,7 @@ class Parser : public ParserState { known_attributes_["cpp_ptr_type"] = true; known_attributes_["cpp_str_type"] = true; known_attributes_["native_inline"] = true; + known_attributes_["native_custom_alloc"] = true; known_attributes_["native_type"] = true; known_attributes_["native_default"] = true; known_attributes_["flexbuffer"] = true; diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 623ada2f1..8b2837953 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -479,7 +479,11 @@ class CppGenerator : public BaseGenerator { } case BASE_TYPE_VECTOR: { const auto type_name = GenTypeNative(type.VectorType(), true, field); - return "std::vector<" + type_name + ">"; + if (type.struct_def && type.struct_def->attributes.Lookup("native_custom_alloc")) { + auto native_custom_alloc = type.struct_def->attributes.Lookup("native_custom_alloc"); + return "std::vector<" + type_name + "," + native_custom_alloc->constant + "<" + type_name + ">>"; + } else + return "std::vector<" + type_name + ">"; } case BASE_TYPE_STRUCT: { auto type_name = WrapInNameSpace(*type.struct_def); @@ -1323,6 +1327,17 @@ class CppGenerator : public BaseGenerator { code_ += " }"; } + void GenOperatorNewDelete(const StructDef & struct_def) { + if (auto native_custom_alloc = struct_def.attributes.Lookup("native_custom_alloc")) { + code_ += " inline void *operator new (std::size_t count) {"; + code_ += " return " + native_custom_alloc->constant + "<{{NATIVE_NAME}}>().allocate(count / sizeof({{NATIVE_NAME}}));"; + code_ += " }"; + code_ += " inline void operator delete (void *ptr) {"; + code_ += " return " + native_custom_alloc->constant + "<{{NATIVE_NAME}}>().deallocate(static_cast<{{NATIVE_NAME}}*>(ptr),1);"; + code_ += " }"; + } + } + void GenNativeTable(const StructDef &struct_def) { const auto native_name = NativeName(Name(struct_def), &struct_def, parser_.opts); code_.SetValue("STRUCT_NAME", Name(struct_def)); @@ -1336,6 +1351,7 @@ class CppGenerator : public BaseGenerator { it != struct_def.fields.vec.end(); ++it) { GenMember(**it); } + GenOperatorNewDelete(struct_def); GenDefaultConstructor(struct_def); code_ += "};"; code_ += ""; @@ -2388,6 +2404,8 @@ class CppGenerator : public BaseGenerator { code_ += " }"; } } + code_.SetValue("NATIVE_NAME", Name(struct_def)); + GenOperatorNewDelete(struct_def); code_ += "};"; code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize)); diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index cc58a1cda..65e7cb86a 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -676,6 +676,10 @@ CheckedError Parser::ParseField(StructDef &struct_def) { } } + auto field_native_custom_alloc = field->attributes.Lookup("native_custom_alloc"); + if (field_native_custom_alloc) + return Error("native_custom_alloc can only be used with a table or struct definition"); + field->native_inline = field->attributes.Lookup("native_inline") != nullptr; if (field->native_inline && !IsStruct(field->value.type)) return Error("native_inline can only be defined on structs'"); diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index 843e308c5204d9c36bad66ae49ac2d37041b4cce..2e247eb3af964b0f0aa98041a26d12cb0ebb965b 100644 GIT binary patch literal 5520 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