Skip to content

Commit 4d3633c

Browse files
committed
Remove all copies of Schema and Map
1 parent b4e893e commit 4d3633c

File tree

3 files changed

+45
-25
lines changed

3 files changed

+45
-25
lines changed

schema/elements.go

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,7 @@ type Schema struct {
3030
once sync.Once
3131
m map[string]TypeDef
3232

33-
// Once used to protect the initialization of `lock` field.
34-
lockOnce sync.Once
35-
// Lock which protects writes to resolvedTypes. Used as pointer so that
36-
// schema may be used as a value type
37-
lock *sync.Mutex
33+
lock sync.Mutex
3834
// Cached results of resolving type references to atoms. Only stores
3935
// type references which require fields of Atom to be overriden.
4036
resolvedTypes map[TypeRef]Atom
@@ -163,6 +159,31 @@ func (m *Map) FindField(name string) (StructField, bool) {
163159
return sf, ok
164160
}
165161

162+
// CopyInto this instance of Map into the other
163+
// If other is nil this method does nothing.
164+
// If other is already initialized, overwrites it with this instance
165+
// Warning: Not thread safe
166+
func (m *Map) CopyInto(dst *Map) {
167+
if dst == nil {
168+
return
169+
}
170+
171+
// Map type is considered immutable so sharing references
172+
dst.Fields = m.Fields
173+
dst.ElementType = m.ElementType
174+
dst.Unions = m.Unions
175+
dst.ElementRelationship = m.ElementRelationship
176+
177+
if m.m != nil {
178+
// If cache is non-nil then the once token had been consumed.
179+
// Must reset token and use it again to ensure same semantics.
180+
dst.once = sync.Once{}
181+
dst.once.Do(func() {
182+
dst.m = m.m
183+
})
184+
}
185+
}
186+
166187
// UnionFields are mapping between the fields that are part of the union and
167188
// their discriminated value. The discriminated value has to be set, and
168189
// should not conflict with other discriminated value in the list.
@@ -289,15 +310,13 @@ func (s *Schema) Resolve(tr TypeRef) (Atom, bool) {
289310
return s.resolveNoOverrides(tr)
290311
}
291312

292-
// Check to see if we have a cached version of this type
293-
s.lockOnce.Do(func() {
294-
s.lock = &sync.Mutex{}
295-
s.resolvedTypes = make(map[TypeRef]Atom)
296-
})
297-
298313
s.lock.Lock()
299314
defer s.lock.Unlock()
300315

316+
if s.resolvedTypes == nil {
317+
s.resolvedTypes = make(map[TypeRef]Atom)
318+
}
319+
301320
var result Atom
302321
var exists bool
303322

@@ -308,7 +327,8 @@ func (s *Schema) Resolve(tr TypeRef) (Atom, bool) {
308327
// Allow field-level electives to override the referred type's modifiers
309328
switch {
310329
case result.Map != nil:
311-
mapCopy := *result.Map
330+
mapCopy := Map{}
331+
result.Map.CopyInto(&mapCopy)
312332
mapCopy.ElementRelationship = *tr.ElementRelationship
313333
result.Map = &mapCopy
314334
case result.List != nil:
@@ -335,7 +355,7 @@ func (s *Schema) Resolve(tr TypeRef) (Atom, bool) {
335355
// If other is nil this method does nothing.
336356
// If other is already initialized, overwrites it with this instance
337357
// Warning: Not thread safe
338-
func (s Schema) CopyInto(dst *Schema) {
358+
func (s *Schema) CopyInto(dst *Schema) {
339359
if dst == nil {
340360
return
341361
}

schema/elements_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func TestCopyInto(t *testing.T) {
161161
theCopy := Schema{}
162162
s.CopyInto(&theCopy)
163163

164-
if !reflect.DeepEqual(s, theCopy) {
164+
if !reflect.DeepEqual(&s, &theCopy) {
165165
t.Fatal("")
166166
}
167167

@@ -170,7 +170,7 @@ func TestCopyInto(t *testing.T) {
170170
theCopy = Schema{}
171171
s.CopyInto(&theCopy)
172172

173-
if !reflect.DeepEqual(s, theCopy) {
173+
if !reflect.DeepEqual(&s, &theCopy) {
174174
t.Fatal("")
175175
}
176176
})

schema/equals_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ func fuzzInterface(i *interface{}, c fuzz.Continue) {
3131
*i = &m
3232
}
3333

34-
func (Schema) Generate(rand *rand.Rand, size int) reflect.Value {
34+
func (*Schema) Generate(rand *rand.Rand, size int) reflect.Value {
3535
s := Schema{}
3636
f := fuzz.New().RandSource(rand).MaxDepth(4)
3737
f.Fuzz(&s)
38-
return reflect.ValueOf(s)
38+
return reflect.ValueOf(&s)
3939
}
4040

41-
func (Map) Generate(rand *rand.Rand, size int) reflect.Value {
41+
func (*Map) Generate(rand *rand.Rand, size int) reflect.Value {
4242
m := Map{}
4343
f := fuzz.New().RandSource(rand).MaxDepth(4).Funcs(fuzzInterface)
4444
f.Fuzz(&m)
45-
return reflect.ValueOf(m)
45+
return reflect.ValueOf(&m)
4646
}
4747

4848
func (TypeDef) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -73,13 +73,13 @@ func TestEquals(t *testing.T) {
7373
// The "copy known fields" section of these function is to break if folks
7474
// add new fields without fixing the Equals function and this test.
7575
funcs := []interface{}{
76-
func(x Schema) bool {
77-
if !x.Equals(&x) {
76+
func(x *Schema) bool {
77+
if !x.Equals(x) {
7878
return false
7979
}
8080
var y Schema
8181
y.Types = x.Types
82-
return x.Equals(&y) == reflect.DeepEqual(&x, &y)
82+
return x.Equals(&y) == reflect.DeepEqual(x, &y)
8383
},
8484
func(x TypeDef) bool {
8585
if !x.Equals(&x) {
@@ -109,16 +109,16 @@ func TestEquals(t *testing.T) {
109109
y.Map = x.Map
110110
return x.Equals(&y) == reflect.DeepEqual(x, y)
111111
},
112-
func(x Map) bool {
113-
if !x.Equals(&x) {
112+
func(x *Map) bool {
113+
if !x.Equals(x) {
114114
return false
115115
}
116116
var y Map
117117
y.ElementType = x.ElementType
118118
y.ElementRelationship = x.ElementRelationship
119119
y.Fields = x.Fields
120120
y.Unions = x.Unions
121-
return x.Equals(&y) == reflect.DeepEqual(&x, &y)
121+
return x.Equals(&y) == reflect.DeepEqual(x, &y)
122122
},
123123
func(x Union) bool {
124124
if !x.Equals(&x) {

0 commit comments

Comments
 (0)