Skip to content

Commit 25cfb20

Browse files
mpvlmyitcv
authored andcommitted
cue/cuecontext: allow concurrent use
This was currently only not allowed for imports. Really import indices should be unique per context, but even in that case, concurrency should be allowed. Fixes #1414 Signed-off-by: Marcel van Lohuizen <mpvl@golang.org> Change-Id: I944357c7b68cd242d19b323a1380c751a7fe49a5 Signed-off-by: Marcel van Lohuizen <mpvl@golang.org> Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/529629 Reviewed-by: Paul Jolly <paul@myitcv.io>
1 parent 8a40ef0 commit 25cfb20

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

cue/cuecontext/cuecontext_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,21 @@ func TestAPI(t *testing.T) {
5454
})
5555
}
5656
}
57+
58+
// TestConcurrency tests whether concurrent use of an index is allowed.
59+
// This test only functions well with the --race flag.
60+
func TestConcurrency(t *testing.T) {
61+
c := New()
62+
go func() {
63+
c.CompileString(`
64+
package foo
65+
a: 1
66+
`)
67+
}()
68+
go func() {
69+
c.CompileString(`
70+
package bar
71+
a: 2
72+
`)
73+
}()
74+
}

internal/core/runtime/build.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ func (x *Runtime) buildSpec(cfg *Config, b *build.Instance, spec *ast.ImportSpec
135135
return nil // TODO: check the builtin package exists here.
136136
}
137137

138-
if v := x.index.importsByBuild[pkg]; v != nil {
138+
if v := x.getNodeFromInstance(pkg); v != nil {
139139
return pkg.Err
140140
}
141141

internal/core/runtime/imports.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,17 @@ var sharedIndex = newIndex()
5858
//
5959
// All instances belonging to the same package should share this index.
6060
type index struct {
61-
// Change this to Instance at some point.
62-
// From *structLit/*Vertex -> Instance
61+
// lock is used to guard imports-related maps.
62+
// TODO: makes these per cuecontext.
63+
lock sync.RWMutex
6364
imports map[*adt.Vertex]*build.Instance
6465
importsByPath map[string]*adt.Vertex
6566
importsByBuild map[*build.Instance]*adt.Vertex
66-
builtinPaths map[string]PackageFunc // Full path
67-
builtinShort map[string]string // Commandline shorthand
67+
68+
// These are initialized during Go package initialization time and do not
69+
// need to be guarded.
70+
builtinPaths map[string]PackageFunc // Full path
71+
builtinShort map[string]string // Commandline shorthand
6872

6973
typeCache sync.Map // map[reflect.Type]evaluated
7074
}
@@ -86,6 +90,9 @@ func (x *index) shortBuiltinToPath(id string) string {
8690
}
8791

8892
func (r *Runtime) AddInst(path string, key *adt.Vertex, p *build.Instance) {
93+
r.index.lock.Lock()
94+
defer r.index.lock.Unlock()
95+
8996
x := r.index
9097
if key == nil {
9198
panic("key must not be nil")
@@ -98,14 +105,23 @@ func (r *Runtime) AddInst(path string, key *adt.Vertex, p *build.Instance) {
98105
}
99106

100107
func (r *Runtime) GetInstanceFromNode(key *adt.Vertex) *build.Instance {
108+
r.index.lock.RLock()
109+
defer r.index.lock.RUnlock()
110+
101111
return r.index.imports[key]
102112
}
103113

104114
func (r *Runtime) getNodeFromInstance(key *build.Instance) *adt.Vertex {
115+
r.index.lock.RLock()
116+
defer r.index.lock.RUnlock()
117+
105118
return r.index.importsByBuild[key]
106119
}
107120

108121
func (r *Runtime) LoadImport(importPath string) (*adt.Vertex, errors.Error) {
122+
r.index.lock.Lock()
123+
defer r.index.lock.Unlock()
124+
109125
x := r.index
110126

111127
key := x.importsByPath[importPath]

0 commit comments

Comments
 (0)