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"
"reflect"
"strings"
"sync"
"time"
"unicode"
)
@ -51,8 +52,45 @@ type cachedStruct struct {
fields []*cachedField
}
var structCache = map[reflect.Type]*cachedStruct{}
var fieldsCache = map[string][]*cachedTags{}
type structsCacheMap struct {
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
// 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 numFields int
cs, isCached := structCache[structType]
cs, isCached := structCache.Get(structType)
if isCached {
structName = cs.name
@ -214,7 +252,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
structName = structType.Name()
numFields = structValue.NumField()
cs = &cachedStruct{name: structName, children: numFields}
structCache[structType] = cs
structCache.Set(structType, cs)
}
validationErrors := &StructErrors{
@ -374,7 +412,7 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
if len(cField.tags) == 0 {
if isSingleField {
cField.tags, isCached = fieldsCache[tag]
cField.tags, isCached = fieldsCache.Get(tag)
}
if !isCached {
@ -404,7 +442,7 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
}
if isSingleField {
fieldsCache[cField.tag] = cField.tags
fieldsCache.Set(cField.tag, cField.tags)
}
}
}

Loading…
Cancel
Save