Răsfoiți Sursa

Merge pull request #741 from pherl/beta-1

fix "memory leaks" in protostream-object files.
Jisi Liu 10 ani în urmă
părinte
comite
f9237d2bcd

+ 30 - 22
src/google/protobuf/util/internal/protostream_objectsource.cc

@@ -47,6 +47,7 @@
 #include <google/protobuf/util/internal/utility.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/once.h>
 #include <google/protobuf/stubs/status_macros.h>
 
 
@@ -648,46 +649,53 @@ Status ProtoStreamObjectSource::RenderFieldMask(
 }
 
 hash_map<string, ProtoStreamObjectSource::TypeRenderer>*
-ProtoStreamObjectSource::CreateRendererMap() {
-  hash_map<string, ProtoStreamObjectSource::TypeRenderer>* result =
-      new hash_map<string, ProtoStreamObjectSource::TypeRenderer>();
-  (*result)["google.protobuf.Timestamp"] =
+    ProtoStreamObjectSource::renderers_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(source_renderers_init_);
+
+void ProtoStreamObjectSource::InitRendererMap() {
+  renderers_ = new hash_map<string, ProtoStreamObjectSource::TypeRenderer>();
+  (*renderers_)["google.protobuf.Timestamp"] =
       &ProtoStreamObjectSource::RenderTimestamp;
-  (*result)["google.protobuf.Duration"] =
+  (*renderers_)["google.protobuf.Duration"] =
       &ProtoStreamObjectSource::RenderDuration;
-  (*result)["google.protobuf.DoubleValue"] =
+  (*renderers_)["google.protobuf.DoubleValue"] =
       &ProtoStreamObjectSource::RenderDouble;
-  (*result)["google.protobuf.FloatValue"] =
+  (*renderers_)["google.protobuf.FloatValue"] =
       &ProtoStreamObjectSource::RenderFloat;
-  (*result)["google.protobuf.Int64Value"] =
+  (*renderers_)["google.protobuf.Int64Value"] =
       &ProtoStreamObjectSource::RenderInt64;
-  (*result)["google.protobuf.UInt64Value"] =
+  (*renderers_)["google.protobuf.UInt64Value"] =
       &ProtoStreamObjectSource::RenderUInt64;
-  (*result)["google.protobuf.Int32Value"] =
+  (*renderers_)["google.protobuf.Int32Value"] =
       &ProtoStreamObjectSource::RenderInt32;
-  (*result)["google.protobuf.UInt32Value"] =
+  (*renderers_)["google.protobuf.UInt32Value"] =
       &ProtoStreamObjectSource::RenderUInt32;
-  (*result)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool;
-  (*result)["google.protobuf.StringValue"] =
+  (*renderers_)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool;
+  (*renderers_)["google.protobuf.StringValue"] =
       &ProtoStreamObjectSource::RenderString;
-  (*result)["google.protobuf.BytesValue"] =
+  (*renderers_)["google.protobuf.BytesValue"] =
       &ProtoStreamObjectSource::RenderBytes;
-  (*result)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
-  (*result)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct;
-  (*result)["google.protobuf.Value"] =
+  (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
+  (*renderers_)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct;
+  (*renderers_)["google.protobuf.Value"] =
       &ProtoStreamObjectSource::RenderStructValue;
-  (*result)["google.protobuf.ListValue"] =
+  (*renderers_)["google.protobuf.ListValue"] =
       &ProtoStreamObjectSource::RenderStructListValue;
-  (*result)["google.protobuf.FieldMask"] =
+  (*renderers_)["google.protobuf.FieldMask"] =
       &ProtoStreamObjectSource::RenderFieldMask;
-  return result;
+  ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
+}
+
+void ProtoStreamObjectSource::DeleteRendererMap() {
+  delete ProtoStreamObjectSource::renderers_;
+  renderers_ = NULL;
 }
 
 // static
 ProtoStreamObjectSource::TypeRenderer*
 ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) {
-  static hash_map<string, TypeRenderer>* renderers = CreateRendererMap();
-  return FindOrNull(*renderers, type_url);
+  ::google::protobuf::GoogleOnceInit(&source_renderers_init_, &InitRendererMap);
+  return FindOrNull(*renderers_, type_url);
 }
 
 Status ProtoStreamObjectSource::RenderField(

+ 3 - 1
src/google/protobuf/util/internal/protostream_objectsource.h

@@ -202,7 +202,9 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
                                         const google::protobuf::Type& type,
                                         StringPiece name, ObjectWriter* ow);
 
-  static hash_map<string, TypeRenderer>* CreateRendererMap();
+  static hash_map<string, TypeRenderer>* renderers_;
+  static void InitRendererMap();
+  static void DeleteRendererMap();
   static TypeRenderer* FindTypeRenderer(const string& type_url);
 
   // Renders a field value to the ObjectWriter.

+ 36 - 28
src/google/protobuf/util/internal/protostream_objectwriter.cc

@@ -39,6 +39,7 @@
 #include <google/protobuf/util/internal/object_location_tracker.h>
 #include <google/protobuf/util/internal/constants.h>
 #include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/once.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/statusor.h>
@@ -1365,60 +1366,67 @@ void ProtoStreamObjectWriter::RenderSimpleDataPiece(
 // Map of functions that are responsible for rendering well known type
 // represented by the key.
 hash_map<string, ProtoStreamObjectWriter::TypeRenderer>*
-ProtoStreamObjectWriter::CreateRendererMap() {
-  google::protobuf::scoped_ptr<hash_map<string, ProtoStreamObjectWriter::TypeRenderer> >
-      result(new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>());
-  (*result)["type.googleapis.com/google.protobuf.Timestamp"] =
+    ProtoStreamObjectWriter::renderers_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(writer_renderers_init_);
+
+void ProtoStreamObjectWriter::InitRendererMap() {
+  renderers_ = new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>();
+  (*renderers_)["type.googleapis.com/google.protobuf.Timestamp"] =
       &ProtoStreamObjectWriter::RenderTimestamp;
-  (*result)["type.googleapis.com/google.protobuf.Duration"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Duration"] =
       &ProtoStreamObjectWriter::RenderDuration;
-  (*result)["type.googleapis.com/google.protobuf.FieldMask"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.FieldMask"] =
       &ProtoStreamObjectWriter::RenderFieldMask;
-  (*result)["type.googleapis.com/google.protobuf.Double"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Double"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.Float"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Float"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.Int64"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Int64"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.UInt64"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.UInt64"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.Int32"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Int32"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.UInt32"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.UInt32"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.Bool"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Bool"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.String"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.String"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.Bytes"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Bytes"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.DoubleValue"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.DoubleValue"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.FloatValue"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.FloatValue"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.Int64Value"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Int64Value"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.UInt64Value"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.UInt64Value"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.Int32Value"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Int32Value"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.UInt32Value"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.UInt32Value"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.BoolValue"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.BoolValue"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.StringValue"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.StringValue"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.BytesValue"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.BytesValue"] =
       &ProtoStreamObjectWriter::RenderWrapperType;
-  (*result)["type.googleapis.com/google.protobuf.Value"] =
+  (*renderers_)["type.googleapis.com/google.protobuf.Value"] =
       &ProtoStreamObjectWriter::RenderStructValue;
-  return result.release();
+  ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
+}
+
+void ProtoStreamObjectWriter::DeleteRendererMap() {
+  delete ProtoStreamObjectWriter::renderers_;
+  renderers_ = NULL;
 }
 
 ProtoStreamObjectWriter::TypeRenderer*
 ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) {
-  static hash_map<string, TypeRenderer>* renderers = CreateRendererMap();
-  return FindOrNull(*renderers, type_url);
+  ::google::protobuf::GoogleOnceInit(&writer_renderers_init_, &InitRendererMap);
+  return FindOrNull(*renderers_, type_url);
 }
 
 ProtoStreamObjectWriter::ProtoElement::ElementType

+ 3 - 1
src/google/protobuf/util/internal/protostream_objectwriter.h

@@ -407,7 +407,9 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
 
   // Helper functions to create the map and find functions responsible for
   // rendering well known types, keyed by type URL.
-  static hash_map<string, TypeRenderer>* CreateRendererMap();
+  static hash_map<string, TypeRenderer>* renderers_;
+  static void InitRendererMap();
+  static void DeleteRendererMap();
   static TypeRenderer* FindTypeRenderer(const string& type_url);
 
   // Returns the ProtoElement::ElementType for the given Type.