add map thread safety

pull/59/head
joeybloggs 10 years ago
parent 0c5fbee316
commit 8c2248a5ce
  1. 50
      validator.go

@ -14,6 +14,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
"sync"
"time" "time"
"unicode" "unicode"
) )
@ -51,8 +52,45 @@ type cachedStruct struct {
fields []*cachedField fields []*cachedField
} }
var structCache = map[reflect.Type]*cachedStruct{} type structsCacheMap struct {
var fieldsCache = map[string][]*cachedTags{} lock sync.RWMutex
m map[reflect.Type]*cachedStruct
}
func (s *structsCacheMap) Get(key reflect.Type) (*cachedStruct, bool) {
s.lock.RLock()
defer s.lock.RUnlock()
value, ok := s.m[key]
return value, ok
}
func (s *structsCacheMap) Set(key reflect.Type, value *cachedStruct) {
s.lock.Lock()
defer s.lock.Unlock()
s.m[key] = value
}
var structCache = &structsCacheMap{m: map[reflect.Type]*cachedStruct{}}
type fieldsCacheMap struct {
lock sync.RWMutex
m map[string][]*cachedTags
}
func (s *fieldsCacheMap) Get(key string) ([]*cachedTags, bool) {
s.lock.RLock()
defer s.lock.RUnlock()
value, ok := s.m[key]
return value, ok
}
func (s *fieldsCacheMap) Set(key string, value []*cachedTags) {
s.lock.Lock()
defer s.lock.Unlock()
s.m[key] = value
}
var fieldsCache = &fieldsCacheMap{m: map[string][]*cachedTags{}}
// FieldError contains a single field's validation error along // FieldError contains a single field's validation error along
// with other properties that may be needed for error message creation // with other properties that may be needed for error message creation
@ -205,7 +243,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
var structName string var structName string
var numFields int var numFields int
cs, isCached := structCache[structType] cs, isCached := structCache.Get(structType)
if isCached { if isCached {
structName = cs.name structName = cs.name
@ -214,7 +252,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
structName = structType.Name() structName = structType.Name()
numFields = structValue.NumField() numFields = structValue.NumField()
cs = &cachedStruct{name: structName, children: numFields} cs = &cachedStruct{name: structName, children: numFields}
structCache[structType] = cs structCache.Set(structType, cs)
} }
validationErrors := &StructErrors{ validationErrors := &StructErrors{
@ -374,7 +412,7 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
if len(cField.tags) == 0 { if len(cField.tags) == 0 {
if isSingleField { if isSingleField {
cField.tags, isCached = fieldsCache[tag] cField.tags, isCached = fieldsCache.Get(tag)
} }
if !isCached { if !isCached {
@ -404,7 +442,7 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
} }
if isSingleField { if isSingleField {
fieldsCache[cField.tag] = cField.tags fieldsCache.Set(cField.tag, cField.tags)
} }
} }
} }

Loading…
Cancel
Save