hclsyntax: Safe concurrent evaluation of splat expressions
Due to the special handling of the anonymous symbol employed to evaluate a splat expression, we need to employ a lock on that symbol so that it's safe for concurrent evaluation. As before, it's not safe to concurrently evaluate the same expression in the same context, but it is now safe to do so as long as all concurrent evaluations have a _distinct_ EvalContext. This fixes #28.
This commit is contained in:
parent
bbbd0ef30d
commit
3006ab4459
@ -2,6 +2,7 @@ package hclsyntax
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/hcl2/hcl"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
@ -1226,13 +1227,24 @@ func (e *SplatExpr) StartRange() hcl.Range {
|
||||
// assigns it a value.
|
||||
type AnonSymbolExpr struct {
|
||||
SrcRange hcl.Range
|
||||
values map[*hcl.EvalContext]cty.Value
|
||||
|
||||
// values and its associated lock are used to isolate concurrent
|
||||
// evaluations of a symbol from one another. It is the calling application's
|
||||
// responsibility to ensure that the same splat expression is not evalauted
|
||||
// concurrently within the _same_ EvalContext, but it is fine and safe to
|
||||
// do cuncurrent evaluations with distinct EvalContexts.
|
||||
values map[*hcl.EvalContext]cty.Value
|
||||
valuesLock sync.RWMutex
|
||||
}
|
||||
|
||||
func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
|
||||
if ctx == nil {
|
||||
return cty.DynamicVal, nil
|
||||
}
|
||||
|
||||
e.valuesLock.RLock()
|
||||
defer e.valuesLock.RUnlock()
|
||||
|
||||
val, exists := e.values[ctx]
|
||||
if !exists {
|
||||
return cty.DynamicVal, nil
|
||||
@ -1243,6 +1255,9 @@ func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics
|
||||
// setValue sets a temporary local value for the expression when evaluated
|
||||
// in the given context, which must be non-nil.
|
||||
func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) {
|
||||
e.valuesLock.Lock()
|
||||
defer e.valuesLock.Unlock()
|
||||
|
||||
if e.values == nil {
|
||||
e.values = make(map[*hcl.EvalContext]cty.Value)
|
||||
}
|
||||
@ -1253,6 +1268,9 @@ func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) {
|
||||
}
|
||||
|
||||
func (e *AnonSymbolExpr) clearValue(ctx *hcl.EvalContext) {
|
||||
e.valuesLock.Lock()
|
||||
defer e.valuesLock.Unlock()
|
||||
|
||||
if e.values == nil {
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user