Skip to content

Commit

Permalink
cue/context: allow concurrent use
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mpvl committed Dec 17, 2021
1 parent 8a40ef0 commit 34d56db
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
18 changes: 18 additions & 0 deletions cue/cuecontext/cuecontext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,21 @@ func TestAPI(t *testing.T) {
})
}
}

// TestConcurrency tests whether concurrent use of an index is allowed.
// This test only functions well with the --race flag.
func TestConcurrency(t *testing.T) {
c := New()
go func() {
c.CompileString(`
package foo
a: 1
`)
}()
go func() {
c.CompileString(`
package bar
a: 2
`)
}()
}
2 changes: 1 addition & 1 deletion internal/core/runtime/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func (x *Runtime) buildSpec(cfg *Config, b *build.Instance, spec *ast.ImportSpec
return nil // TODO: check the builtin package exists here.
}

if v := x.index.importsByBuild[pkg]; v != nil {
if v := x.getNodeFromInstance(pkg); v != nil {
return pkg.Err
}

Expand Down
24 changes: 20 additions & 4 deletions internal/core/runtime/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,17 @@ var sharedIndex = newIndex()
//
// All instances belonging to the same package should share this index.
type index struct {
// Change this to Instance at some point.
// From *structLit/*Vertex -> Instance
// lock is used to guard imports-related maps.
// TODO: makes these per cuecontext.
lock sync.RWMutex
imports map[*adt.Vertex]*build.Instance
importsByPath map[string]*adt.Vertex
importsByBuild map[*build.Instance]*adt.Vertex
builtinPaths map[string]PackageFunc // Full path
builtinShort map[string]string // Commandline shorthand

// These are initialized during Go package initialization time and do not
// need to be guarded.
builtinPaths map[string]PackageFunc // Full path
builtinShort map[string]string // Commandline shorthand

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

func (r *Runtime) AddInst(path string, key *adt.Vertex, p *build.Instance) {
r.index.lock.Lock()
defer r.index.lock.Unlock()

x := r.index
if key == nil {
panic("key must not be nil")
Expand All @@ -98,14 +105,23 @@ func (r *Runtime) AddInst(path string, key *adt.Vertex, p *build.Instance) {
}

func (r *Runtime) GetInstanceFromNode(key *adt.Vertex) *build.Instance {
r.index.lock.RLock()
defer r.index.lock.RUnlock()

return r.index.imports[key]
}

func (r *Runtime) getNodeFromInstance(key *build.Instance) *adt.Vertex {
r.index.lock.RLock()
defer r.index.lock.RUnlock()

return r.index.importsByBuild[key]
}

func (r *Runtime) LoadImport(importPath string) (*adt.Vertex, errors.Error) {
r.index.lock.Lock()
defer r.index.lock.Unlock()

x := r.index

key := x.importsByPath[importPath]
Expand Down

0 comments on commit 34d56db

Please sign in to comment.