Commit 53a89773 authored by rmawatson's avatar rmawatson Committed by Wouter van Oortmerssen

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 <typename T> class custom_alloc_name : public std::allocator<T> {
public:

 typedef T*       pointer;

 template <class U>
 struct rebind {
  typedef custom_alloc_name<U> other;
 };

 pointer allocate(const std::size_t n) {
      return ....;
 }

 void deallocate(T* ptr, std::size_t n) {
    ...
 }

 custom_alloc_name() throw() {}
 template <class U> custom_alloc_name(const custom_alloc_name<U>&) throw() {}
};
};
parent ba08b0ec
...@@ -126,6 +126,45 @@ The following attributes are specific to the object-based API code generation: ...@@ -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 "native_inline", the value specified with this attribute will be included
verbatim in the class constructor initializer list for this member. 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 <typename T> struct custom_allocator : public std::allocator<T> {
typedef T *pointer;
template <class U>
struct rebind {
typedef custom_allocator<U> other;
};
pointer allocate(const std::size_t n) {
return std::allocator<T>::allocate(n);
}
void deallocate(T* ptr, std::size_t n) {
return std::allocator<T>::deallocate(ptr,n);
}
custom_allocator() throw() {}
template <class U>
custom_allocator(const custom_allocator<U>&) throw() {}
};
- `native_type`' "type" (on a struct): In some cases, a more optimal C++ data - `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: type exists for a given struct. For example, the following schema:
......
...@@ -656,10 +656,10 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) { ...@@ -656,10 +656,10 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) {
return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t)); return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
} }
template <typename T> const T* data(const std::vector<T> &v) { template <typename T, typename Alloc> const T* data(const std::vector<T, Alloc> &v) {
return v.empty() ? nullptr : &v.front(); return v.empty() ? nullptr : &v.front();
} }
template <typename T> T* data(std::vector<T> &v) { template <typename T, typename Alloc> T* data(std::vector<T, Alloc> &v) {
return v.empty() ? nullptr : &v.front(); return v.empty() ? nullptr : &v.front();
} }
...@@ -1283,8 +1283,8 @@ class FlatBufferBuilder ...@@ -1283,8 +1283,8 @@ class FlatBufferBuilder
/// serialize into the buffer as a `vector`. /// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs( template<typename T, typename Alloc> Offset<Vector<const T *>> CreateVectorOfStructs(
const std::vector<T> &v) { const std::vector<T, Alloc> &v) {
return CreateVectorOfStructs(data(v), v.size()); return CreateVectorOfStructs(data(v), v.size());
} }
......
...@@ -526,6 +526,7 @@ class Parser : public ParserState { ...@@ -526,6 +526,7 @@ class Parser : public ParserState {
known_attributes_["cpp_ptr_type"] = true; known_attributes_["cpp_ptr_type"] = true;
known_attributes_["cpp_str_type"] = true; known_attributes_["cpp_str_type"] = true;
known_attributes_["native_inline"] = true; known_attributes_["native_inline"] = true;
known_attributes_["native_custom_alloc"] = true;
known_attributes_["native_type"] = true; known_attributes_["native_type"] = true;
known_attributes_["native_default"] = true; known_attributes_["native_default"] = true;
known_attributes_["flexbuffer"] = true; known_attributes_["flexbuffer"] = true;
......
...@@ -479,7 +479,11 @@ class CppGenerator : public BaseGenerator { ...@@ -479,7 +479,11 @@ class CppGenerator : public BaseGenerator {
} }
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeNative(type.VectorType(), true, field); 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: { case BASE_TYPE_STRUCT: {
auto type_name = WrapInNameSpace(*type.struct_def); auto type_name = WrapInNameSpace(*type.struct_def);
...@@ -1323,6 +1327,17 @@ class CppGenerator : public BaseGenerator { ...@@ -1323,6 +1327,17 @@ class CppGenerator : public BaseGenerator {
code_ += " }"; 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) { void GenNativeTable(const StructDef &struct_def) {
const auto native_name = NativeName(Name(struct_def), &struct_def, parser_.opts); const auto native_name = NativeName(Name(struct_def), &struct_def, parser_.opts);
code_.SetValue("STRUCT_NAME", Name(struct_def)); code_.SetValue("STRUCT_NAME", Name(struct_def));
...@@ -1336,6 +1351,7 @@ class CppGenerator : public BaseGenerator { ...@@ -1336,6 +1351,7 @@ class CppGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
GenMember(**it); GenMember(**it);
} }
GenOperatorNewDelete(struct_def);
GenDefaultConstructor(struct_def); GenDefaultConstructor(struct_def);
code_ += "};"; code_ += "};";
code_ += ""; code_ += "";
...@@ -2388,6 +2404,8 @@ class CppGenerator : public BaseGenerator { ...@@ -2388,6 +2404,8 @@ class CppGenerator : public BaseGenerator {
code_ += " }"; code_ += " }";
} }
} }
code_.SetValue("NATIVE_NAME", Name(struct_def));
GenOperatorNewDelete(struct_def);
code_ += "};"; code_ += "};";
code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize)); code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize));
......
...@@ -676,6 +676,10 @@ CheckedError Parser::ParseField(StructDef &struct_def) { ...@@ -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; field->native_inline = field->attributes.Lookup("native_inline") != nullptr;
if (field->native_inline && !IsStruct(field->value.type)) if (field->native_inline && !IsStruct(field->value.type))
return Error("native_inline can only be defined on structs'"); return Error("native_inline can only be defined on structs'");
......
No preview for this file type
// automatically generated by the FlatBuffers compiler, do not modify // automatically generated by the FlatBuffers compiler, do not modify
import * as NS9459827973991502386 from "./namespace_test1_generated"; import * as NS11563891686210618450 from "./namespace_test1_generated";
/** /**
* @constructor * @constructor
*/ */
...@@ -39,24 +39,24 @@ static getRootAsTableInFirstNS(bb:flatbuffers.ByteBuffer, obj?:TableInFirstNS):T ...@@ -39,24 +39,24 @@ static getRootAsTableInFirstNS(bb:flatbuffers.ByteBuffer, obj?:TableInFirstNS):T
* @param {NamespaceA.NamespaceB.TableInNestedNS=} obj * @param {NamespaceA.NamespaceB.TableInNestedNS=} obj
* @returns {NamespaceA.NamespaceB.TableInNestedNS|null} * @returns {NamespaceA.NamespaceB.TableInNestedNS|null}
*/ */
fooTable(obj?:NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS):NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS|null { fooTable(obj?:NS11563891686210618450.NamespaceA.NamespaceB.TableInNestedNS):NS11563891686210618450.NamespaceA.NamespaceB.TableInNestedNS|null {
var offset = this.bb.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? (obj || new NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; return offset ? (obj || new NS11563891686210618450.NamespaceA.NamespaceB.TableInNestedNS).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
}; };
/** /**
* @returns {NamespaceA.NamespaceB.EnumInNestedNS} * @returns {NamespaceA.NamespaceB.EnumInNestedNS}
*/ */
fooEnum():NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS { fooEnum():NS11563891686210618450.NamespaceA.NamespaceB.EnumInNestedNS {
var offset = this.bb.__offset(this.bb_pos, 6); var offset = this.bb.__offset(this.bb_pos, 6);
return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb.readInt8(this.bb_pos + offset)) : NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS.A; return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb.readInt8(this.bb_pos + offset)) : NS11563891686210618450.NamespaceA.NamespaceB.EnumInNestedNS.A;
}; };
/** /**
* @param {NamespaceA.NamespaceB.EnumInNestedNS} value * @param {NamespaceA.NamespaceB.EnumInNestedNS} value
* @returns {boolean} * @returns {boolean}
*/ */
mutate_foo_enum(value:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS):boolean { mutate_foo_enum(value:NS11563891686210618450.NamespaceA.NamespaceB.EnumInNestedNS):boolean {
var offset = this.bb.__offset(this.bb_pos, 6); var offset = this.bb.__offset(this.bb_pos, 6);
if (offset === 0) { if (offset === 0) {
...@@ -71,9 +71,9 @@ mutate_foo_enum(value:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS ...@@ -71,9 +71,9 @@ mutate_foo_enum(value:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS
* @param {NamespaceA.NamespaceB.StructInNestedNS=} obj * @param {NamespaceA.NamespaceB.StructInNestedNS=} obj
* @returns {NamespaceA.NamespaceB.StructInNestedNS|null} * @returns {NamespaceA.NamespaceB.StructInNestedNS|null}
*/ */
fooStruct(obj?:NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS):NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS|null { fooStruct(obj?:NS11563891686210618450.NamespaceA.NamespaceB.StructInNestedNS):NS11563891686210618450.NamespaceA.NamespaceB.StructInNestedNS|null {
var offset = this.bb.__offset(this.bb_pos, 8); var offset = this.bb.__offset(this.bb_pos, 8);
return offset ? (obj || new NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS).__init(this.bb_pos + offset, this.bb) : null; return offset ? (obj || new NS11563891686210618450.NamespaceA.NamespaceB.StructInNestedNS).__init(this.bb_pos + offset, this.bb) : null;
}; };
/** /**
...@@ -95,8 +95,8 @@ static addFooTable(builder:flatbuffers.Builder, fooTableOffset:flatbuffers.Offse ...@@ -95,8 +95,8 @@ static addFooTable(builder:flatbuffers.Builder, fooTableOffset:flatbuffers.Offse
* @param {flatbuffers.Builder} builder * @param {flatbuffers.Builder} builder
* @param {NamespaceA.NamespaceB.EnumInNestedNS} fooEnum * @param {NamespaceA.NamespaceB.EnumInNestedNS} fooEnum
*/ */
static addFooEnum(builder:flatbuffers.Builder, fooEnum:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS) { static addFooEnum(builder:flatbuffers.Builder, fooEnum:NS11563891686210618450.NamespaceA.NamespaceB.EnumInNestedNS) {
builder.addFieldInt8(1, fooEnum, NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS.A); builder.addFieldInt8(1, fooEnum, NS11563891686210618450.NamespaceA.NamespaceB.EnumInNestedNS.A);
}; };
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment