Generate pargs an presult helpers in C++ to be more efficient in thrift
Summary: Copy construction is the pits. Avoid it at all costs.
Reviewed By: aditya
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664939 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 b6de861..8e2bbdf 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -353,7 +353,10 @@
*/
void t_cpp_generator::generate_struct_definition(ofstream& out,
t_struct* tstruct,
- bool is_exception) {
+ bool is_exception,
+ bool pointers,
+ bool read,
+ bool write) {
string extends = "";
if (is_exception) {
extends = " : public facebook::thrift::TException";
@@ -372,20 +375,22 @@
// Default constructor
bool init_ctor = false;
- for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- t_type* t = (*m_iter)->get_type();
- while (t->is_typedef()) {
- t = ((t_typedef*)t)->get_type();
- }
- if (t->is_base_type() &&
- ((t_base_type*)t)->get_base() != t_base_type::TYPE_STRING) {
- if (!init_ctor) {
- init_ctor = true;
- indent(out) <<
- tstruct->get_name() << "() : ";
- out << (*m_iter)->get_name() << "(0)";
- } else {
- out << ", " << (*m_iter)->get_name() << "(0)";
+ if (!pointers) {
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ t_type* t = (*m_iter)->get_type();
+ while (t->is_typedef()) {
+ t = ((t_typedef*)t)->get_type();
+ }
+ if (t->is_base_type() &&
+ ((t_base_type*)t)->get_base() != t_base_type::TYPE_STRING) {
+ if (!init_ctor) {
+ init_ctor = true;
+ indent(out) <<
+ tstruct->get_name() << "() : ";
+ out << (*m_iter)->get_name() << "(0)";
+ } else {
+ out << ", " << (*m_iter)->get_name() << "(0)";
+ }
}
}
}
@@ -400,11 +405,11 @@
// Declare all fields
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
indent(out) <<
- declare_field(*m_iter) << endl;
+ declare_field(*m_iter, false, pointers && !(*m_iter)->get_type()->is_xception(), !read) << endl;
}
// Isset struct has boolean fields
- if (members.size() > 0) {
+ if (members.size() > 0 && (!pointers || read)) {
out <<
endl <<
indent() <<"struct __isset {" << endl;
@@ -436,9 +441,16 @@
}
out <<
- endl <<
- indent() << "uint32_t read(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot);" << endl <<
- indent() << "uint32_t write(boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) const;" << endl <<
+ endl;
+ if (read) {
+ out <<
+ indent() << "uint32_t read(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot);" << endl;
+ }
+ if (write) {
+ out <<
+ indent() << "uint32_t write(boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) const;" << endl;
+ }
+ out <<
endl;
indent_down();
@@ -454,7 +466,8 @@
* @param tstruct The struct
*/
void t_cpp_generator::generate_struct_reader(ofstream& out,
- t_struct* tstruct) {
+ t_struct* tstruct,
+ bool pointers) {
indent(out) <<
"uint32_t " << tstruct->get_name() << "::read(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot) {" << endl;
indent_up();
@@ -499,7 +512,11 @@
indent(out) <<
"case " << (*f_iter)->get_key() << ":" << endl;
indent_up();
- generate_deserialize_field(out, *f_iter, "this->");
+ if (pointers && !(*f_iter)->get_type()->is_xception()) {
+ generate_deserialize_field(out, *f_iter, "(*(this->", "))");
+ } else {
+ generate_deserialize_field(out, *f_iter, "this->");
+ }
out <<
indent() << "this->__isset." << (*f_iter)->get_name() << " = true;" << endl <<
indent() << "break;" << endl;
@@ -537,7 +554,8 @@
* @param tstruct The struct
*/
void t_cpp_generator::generate_struct_writer(ofstream& out,
- t_struct* tstruct) {
+ t_struct* tstruct,
+ bool pointers) {
string name = tstruct->get_name();
const vector<t_field*>& fields = tstruct->get_members();
vector<t_field*>::const_iterator f_iter;
@@ -559,7 +577,11 @@
type_to_enum((*f_iter)->get_type()) << ", " <<
(*f_iter)->get_key() << ");" << endl;
// Write field contents
- generate_serialize_field(out, *f_iter, "this->");
+ if (pointers) {
+ generate_serialize_field(out, *f_iter, "(*(this->", "))");
+ } else {
+ generate_serialize_field(out, *f_iter, "this->");
+ }
// Write field closer
indent(out) <<
"xfer += oprot->writeFieldEnd();" << endl;
@@ -585,7 +607,8 @@
* @param tstruct The result struct
*/
void t_cpp_generator::generate_struct_result_writer(ofstream& out,
- t_struct* tstruct) {
+ t_struct* tstruct,
+ bool pointers) {
string name = tstruct->get_name();
const vector<t_field*>& fields = tstruct->get_members();
vector<t_field*>::const_iterator f_iter;
@@ -625,7 +648,11 @@
type_to_enum((*f_iter)->get_type()) << ", " <<
(*f_iter)->get_key() << ");" << endl;
// Write field contents
- generate_serialize_field(out, *f_iter, "this->");
+ if (pointers) {
+ generate_serialize_field(out, *f_iter, "(*(this->", "))");
+ } else {
+ generate_serialize_field(out, *f_iter, "this->");
+ }
// Write field closer
indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
@@ -728,12 +755,17 @@
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
t_struct* ts = (*f_iter)->get_arglist();
string name_orig = ts->get_name();
+
ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args");
- generate_struct_definition(f_service_, ts);
+ generate_struct_definition(f_service_, ts, false);
generate_struct_reader(f_service_, ts);
generate_struct_writer(f_service_, ts);
- generate_function_helpers(tservice, *f_iter);
+ ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs");
+ generate_struct_definition(f_service_, ts, false, true, false, true);
+ generate_struct_writer(f_service_, ts, true);
ts->set_name(name_orig);
+
+ generate_function_helpers(tservice, *f_iter);
}
}
@@ -1068,8 +1100,8 @@
scope_up(f_service_);
// Function arguments and results
- string argsname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_args";
- string resultname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_result";
+ string argsname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs";
+ string resultname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_presult";
// Serialize the request
f_service_ <<
@@ -1080,7 +1112,7 @@
for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
f_service_ <<
- indent() << "args." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << ";" << endl;
+ indent() << "args." << (*fld_iter)->get_name() << " = &" << (*fld_iter)->get_name() << ";" << endl;
}
f_service_ <<
@@ -1117,8 +1149,24 @@
indent_down();
f_service_ <<
- indent() << "}" << endl <<
- indent() << resultname << " result;" << endl <<
+ indent() << "}" << endl;
+
+ if (!(*f_iter)->get_returntype()->is_void() &&
+ !is_complex_type((*f_iter)->get_returntype())) {
+ t_field returnfield((*f_iter)->get_returntype(), "_return");
+ f_service_ <<
+ indent() << declare_field(&returnfield) << endl;
+ }
+
+ f_service_ <<
+ indent() << resultname << " result;" << endl;
+
+ if (!(*f_iter)->get_returntype()->is_void()) {
+ f_service_ <<
+ indent() << "result.success = &_return;" << endl;
+ }
+
+ f_service_ <<
indent() << "result.read(iprot_);" << endl <<
indent() << "iprot_->readMessageEnd();" << endl <<
endl;
@@ -1128,13 +1176,13 @@
if (is_complex_type((*f_iter)->get_returntype())) {
f_service_ <<
indent() << "if (result.__isset.success) {" << endl <<
- indent() << " _return = result.success;" << endl <<
+ indent() << " // _return pointer has now been filled" << endl <<
indent() << " return;" << endl <<
indent() << "}" << endl;
} else {
f_service_ <<
indent() << "if (result.__isset.success) {" << endl <<
- indent() << " return result.success;" << endl <<
+ indent() << " return _return;" << endl <<
indent() << "}" << endl;
}
}
@@ -1332,9 +1380,14 @@
result.append(*f_iter);
}
- generate_struct_definition(f_service_, &result);
+ generate_struct_definition(f_service_, &result, false);
generate_struct_reader(f_service_, &result);
generate_struct_result_writer(f_service_, &result);
+
+ result.set_name(tservice->get_name() + "_" + tfunction->get_name() + "_presult");
+ generate_struct_definition(f_service_, &result, false, true, true, false);
+ generate_struct_reader(f_service_, &result, true);
+
}
/**
@@ -1546,7 +1599,8 @@
*/
void t_cpp_generator::generate_deserialize_field(ofstream& out,
t_field* tfield,
- string prefix) {
+ string prefix,
+ string suffix) {
t_type* type = tfield->get_type();
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
@@ -1557,7 +1611,7 @@
prefix + tfield->get_name();
}
- string name = prefix + tfield->get_name();
+ string name = prefix + tfield->get_name() + suffix;
if (type->is_struct() || type->is_xception()) {
generate_deserialize_struct(out, (t_struct*)type, name);
@@ -1747,29 +1801,30 @@
*/
void t_cpp_generator::generate_serialize_field(ofstream& out,
t_field* tfield,
- string prefix) {
+ string prefix,
+ string suffix) {
t_type* type = tfield->get_type();
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
}
+ string name = prefix + tfield->get_name() + suffix;
+
// Do nothing for void types
if (type->is_void()) {
- throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " +
- prefix + tfield->get_name();
+ throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
}
+
+
if (type->is_struct() || type->is_xception()) {
generate_serialize_struct(out,
(t_struct*)type,
- prefix + tfield->get_name());
+ name);
} else if (type->is_container()) {
- generate_serialize_container(out,
- type,
- prefix + tfield->get_name());
+ generate_serialize_container(out, type, name);
} else if (type->is_base_type() || type->is_enum()) {
- string name = prefix + tfield->get_name();
indent(out) <<
"xfer += oprot->";
@@ -1809,9 +1864,8 @@
}
out << endl;
} else {
- printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
- prefix.c_str(),
- tfield->get_name().c_str(),
+ printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n",
+ name.c_str(),
type_name(type).c_str());
}
}
@@ -2000,7 +2054,7 @@
return "const " + bname;
}
}
-
+
// Check for a custom overloaded C++ name
if (ttype->is_container()) {
string cname;
@@ -2046,7 +2100,11 @@
}
if (arg) {
- return "const " + pname + "&";
+ if (is_complex_type(ttype)) {
+ return "const " + pname + "&";
+ } else {
+ return "const " + pname;
+ }
} else {
return pname;
}
@@ -2087,9 +2145,17 @@
* @param ttype The type
* @return Field declaration, i.e. int x = 0;
*/
-string t_cpp_generator::declare_field(t_field* tfield, bool init) {
+string t_cpp_generator::declare_field(t_field* tfield, bool init, bool pointer, bool constant) {
// TODO(mcslee): do we ever need to initialize the field?
- string result = type_name(tfield->get_type()) + " " + tfield->get_name();
+ string result = "";
+ if (constant) {
+ result += "const ";
+ }
+ result += type_name(tfield->get_type());
+ if (pointer) {
+ result += "*";
+ }
+ result += " " + tfield->get_name();
if (init) {
t_type* type = tfield->get_type();
while (type->is_typedef()) {
diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h
index 5a1cbf6..48241ab 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.h
+++ b/compiler/cpp/src/generate/t_cpp_generator.h
@@ -49,10 +49,10 @@
void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
std::string render_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
- void generate_struct_definition (std::ofstream& out, t_struct* tstruct, bool is_exception=false);
- void generate_struct_reader (std::ofstream& out, t_struct* tstruct);
- void generate_struct_writer (std::ofstream& out, t_struct* tstruct);
- void generate_struct_result_writer (std::ofstream& out, t_struct* tstruct);
+ void generate_struct_definition (std::ofstream& out, t_struct* tstruct, bool is_exception=false, bool pointers=false, bool read=true, bool write=true);
+ void generate_struct_reader (std::ofstream& out, t_struct* tstruct, bool pointers=false);
+ void generate_struct_writer (std::ofstream& out, t_struct* tstruct, bool pointers=false);
+ void generate_struct_result_writer (std::ofstream& out, t_struct* tstruct, bool pointers=false);
/**
* Service-level generation functions
@@ -74,7 +74,8 @@
void generate_deserialize_field (std::ofstream& out,
t_field* tfield,
- std::string prefix="");
+ std::string prefix="",
+ std::string suffix="");
void generate_deserialize_struct (std::ofstream& out,
t_struct* tstruct,
@@ -98,7 +99,8 @@
void generate_serialize_field (std::ofstream& out,
t_field* tfield,
- std::string prefix="");
+ std::string prefix="",
+ std::string suffix="");
void generate_serialize_struct (std::ofstream& out,
t_struct* tstruct,
@@ -129,7 +131,7 @@
std::string namespace_close(std::string ns);
std::string type_name(t_type* ttype, bool in_typedef=false, bool arg=false);
std::string base_type_name(t_base_type::t_base tbase);
- std::string declare_field(t_field* tfield, bool init=false);
+ std::string declare_field(t_field* tfield, bool init=false, bool pointer=false, bool constant=false);
std::string function_signature(t_function* tfunction, std::string prefix="");
std::string argument_list(t_struct* tstruct);
std::string type_to_enum(t_type* ttype);