From: David Reiss Date: Tue, 4 Sep 2007 21:31:04 +0000 (+0000) Subject: Thrift: Slight tweaks to local reflection. X-Git-Tag: 0.2.0~1226 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=47557bc8ad061a90c88d485979009c2ee8237854;p=common%2Fthrift.git Thrift: Slight tweaks to local reflection. Summary: Local reflection typespecs for structs now have a dummy T_STOP field at the end so we don't have to check the size on every iteration. They also contain information about which fields are optional. Also put a static pointer to the reflection in each structure. Reviewed By: mcslee Test Plan: test/DenseLinkingTest.thrift Revert Plan: ok git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665246 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index 10127fc3..4a6befdc 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -445,6 +445,13 @@ void t_cpp_generator::generate_struct_definition(ofstream& out, endl << indent() << "virtual ~" << tstruct->get_name() << "() throw() {}" << endl << endl; + // Pointer to this structure's reflection local typespec. + if (gen_dense_) { + indent(out) << + "static facebook::thrift::reflection::local::TypeSpec* local_reflection;" << + endl << endl; + } + // Declare all fields for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << @@ -610,22 +617,32 @@ void t_cpp_generator::generate_local_reflection(std::ofstream& out, generate_local_reflection(out, ((t_map*)ttype)->get_key_type(), is_definition); generate_local_reflection(out, ((t_map*)ttype)->get_val_type(), is_definition); } else if (ttype->is_struct() || ttype->is_xception()) { + // Hacky hacky. For efficiency and convenience, we need a dummy "T_STOP" + // type at the end of our typespec array. Unfortunately, there is no + // T_STOP type, so we use the global void type, and special case it when + // generating its typespec. + const vector& members = ((t_struct*)ttype)->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_local_reflection(out, (**m_iter).get_type(), is_definition); } + generate_local_reflection(out, g_type_void, is_definition); - // For definitions of structures, do the arrays of tags and field specs also. + // For definitions of structures, do the arrays of metas and field specs also. if (is_definition) { - indent(out) << "int16_t " << local_reflection_name("ftags", ttype) <<"[] = {" << endl; + out << + indent() << "facebook::thrift::reflection::local::FieldMeta" << endl << + indent() << local_reflection_name("metas", ttype) <<"[] = {" << endl; indent_up(); - indent(out); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - out << (*m_iter)->get_key() << ", "; + indent(out) << "{ " << (*m_iter)->get_key() << ", " << + (((*m_iter)->get_req() == t_field::OPTIONAL) ? "true" : "false") << + " }," << endl; } + // Zero for the T_STOP marker. + indent(out) << "{ 0, false }" << endl << "};" << endl; indent_down(); - out << endl << "};" << endl; out << indent() << "facebook::thrift::reflection::local::TypeSpec*" << endl << @@ -635,6 +652,8 @@ void t_cpp_generator::generate_local_reflection(std::ofstream& out, indent(out) << "&" << local_reflection_name("typespec", (*m_iter)->get_type()) << "," << endl; } + indent(out) << "&" << + local_reflection_name("typespec", g_type_void) << "," << endl; indent_down(); indent(out) << "};" << endl; } @@ -654,12 +673,16 @@ void t_cpp_generator::generate_local_reflection(std::ofstream& out, indent_up(); - indent(out) << type_to_enum(ttype); + if (ttype->is_void()) { + indent(out) << "facebook::thrift::protocol::T_STOP"; + } else { + indent(out) << type_to_enum(ttype); + } if (ttype->is_struct()) { out << "," << endl << indent() << ((t_struct*)ttype)->get_members().size() << "," << endl << - indent() << local_reflection_name("ftags", ttype) << "," << endl << + indent() << local_reflection_name("metas", ttype) << "," << endl << indent() << local_reflection_name("specs", ttype); } else if (ttype->is_list()) { out << "," << endl << @@ -678,6 +701,16 @@ void t_cpp_generator::generate_local_reflection(std::ofstream& out, out << ");" << endl << endl; indent_down(); + + // If this is a struct and we are in the implementaion file, + // also set the class's static pointer to its reflection. + if (ttype->is_struct() && is_definition) { + indent(out) << + "facebook::thrift::reflection::local::TypeSpec* " << + ttype->get_name() << "::local_reflection = " << endl << + indent() << " &" << local_reflection_name("typespec", ttype) << ";" << + endl << endl; + } } /** diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc index e0ff21fb..43620296 100644 --- a/compiler/cpp/src/main.cc +++ b/compiler/cpp/src/main.cc @@ -533,6 +533,8 @@ void generate_all_fingerprints(t_program* program) { st->generate_fingerprint(); } + g_type_void->generate_fingerprint(); + // If you want to generate fingerprints for implicit structures, start here. /* const vector& services = program->get_services(); diff --git a/lib/cpp/src/TReflectionLocal.h b/lib/cpp/src/TReflectionLocal.h index 6f082e72..414a0ebf 100644 --- a/lib/cpp/src/TReflectionLocal.h +++ b/lib/cpp/src/TReflectionLocal.h @@ -21,13 +21,21 @@ using facebook::thrift::protocol::TType; * @author David Reiss */ +struct FieldMeta { + int16_t tags; + bool is_optional; +}; + struct TypeSpec { // Use an anonymous union here so we can fit two TypeSpecs in one cache line. union { struct { // Use parallel arrays here for denser packing (of the arrays). - int16_t* ftags; + FieldMeta* metas; TypeSpec** specs; + // n_fields is only used for debugging, but it should only add + // a minimimal amount to the effective size of this structure + // because of alignment restrictions. int n_fields; } tstruct; struct { @@ -47,11 +55,11 @@ struct TypeSpec { TypeSpec(TType ttype) : ttype(ttype) {} - TypeSpec(TType ttype, int n_fields, int16_t* ftags, TypeSpec** specs) : + TypeSpec(TType ttype, int n_fields, FieldMeta* metas, TypeSpec** specs) : ttype(ttype) { tstruct.n_fields = n_fields; - tstruct.ftags = ftags; + tstruct.metas = metas; tstruct.specs = specs; }