Browse Source

goprotobuf: Cache extension properties.

Also add some struct field tags to work with go1.1.

R=nigeltao
CC=golang-dev
https://codereview.appspot.com/6980045
David Symonds 13 years ago
parent
commit
29d5d392ac

+ 39 - 4
proto/extensions.go

@@ -39,6 +39,7 @@ import (
 	"errors"
 	"reflect"
 	"strconv"
+	"sync"
 )
 
 // ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
@@ -117,6 +118,42 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
 	return nil
 }
 
+// extPropKey is sufficient to uniquely identify an extension.
+type extPropKey struct {
+	base  reflect.Type
+	field int32
+}
+
+var extProp = struct {
+	sync.RWMutex
+	m map[extPropKey]*Properties
+}{
+	m: make(map[extPropKey]*Properties),
+}
+
+func extensionProperties(ed *ExtensionDesc) *Properties {
+	key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
+
+	extProp.RLock()
+	if prop, ok := extProp.m[key]; ok {
+		extProp.RUnlock()
+		return prop
+	}
+	extProp.RUnlock()
+
+	extProp.Lock()
+	defer extProp.Unlock()
+	// Check again.
+	if prop, ok := extProp.m[key]; ok {
+		return prop
+	}
+
+	prop := new(Properties)
+	prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
+	extProp.m[key] = prop
+	return prop
+}
+
 // encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m.
 func encodeExtensionMap(m map[int32]Extension) error {
 	for k, e := range m {
@@ -130,8 +167,7 @@ func encodeExtensionMap(m map[int32]Extension) error {
 		// the last time this function was called.
 
 		et := reflect.TypeOf(e.desc.ExtensionType)
-		props := new(Properties)
-		props.Init(et, "unknown_name", e.desc.Tag, nil)
+		props := extensionProperties(e.desc)
 
 		p := NewBuffer(nil)
 		// If e.value has type T, the encoder expects a *struct{ X T }.
@@ -204,8 +240,7 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 	t := reflect.TypeOf(extension.ExtensionType)
 	rep := extension.repeated()
 
-	props := &Properties{}
-	props.Init(t, "irrelevant_name", extension.Tag, nil)
+	props := extensionProperties(extension)
 
 	// t is a pointer to a struct, pointer to basic type or a slice.
 	// Allocate a "field" to store the pointer/slice itself; the

+ 1 - 1
protoc-gen-go/generator/generator.go

@@ -929,7 +929,7 @@ func (g *Generator) generate(file *FileDescriptor) {
 		return
 	}
 	g.Reset()
-	err = (&printer.Config{printer.TabIndent | printer.UseSpaces, 8}).Fprint(g, fset, ast)
+	err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast)
 	if err != nil {
 		g.Fail("generated Go source code could not be reformatted:", err.Error())
 	}

+ 1 - 0
protoc-gen-go/testdata/my_test/test.proto

@@ -41,6 +41,7 @@ enum HatType {
 }
 
 enum Days {
+
   MONDAY = 1;
   TUESDAY = 2;
   LUNDI = 1;  // same value as MONDAY