From e7336cc3bfcf60eb775c60509d521e92a5a3b6fe Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Thu, 21 Mar 2024 21:15:18 +0300 Subject: [PATCH] replacer: use RWMutex to protect static provider (#6184) --- replacer.go | 17 ++++++++++++++--- replacer_test.go | 4 ++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/replacer.go b/replacer.go index 046be867a..2ad5b8bcb 100644 --- a/replacer.go +++ b/replacer.go @@ -22,13 +22,15 @@ import ( "runtime" "strconv" "strings" + "sync" "time" ) // NewReplacer returns a new Replacer. func NewReplacer() *Replacer { rep := &Replacer{ - static: make(map[string]any), + static: make(map[string]any), + mapMutex: &sync.RWMutex{}, } rep.providers = []ReplacerFunc{ globalDefaultReplacements, @@ -41,7 +43,8 @@ func NewReplacer() *Replacer { // without the global default replacements. func NewEmptyReplacer() *Replacer { rep := &Replacer{ - static: make(map[string]any), + static: make(map[string]any), + mapMutex: &sync.RWMutex{}, } rep.providers = []ReplacerFunc{ rep.fromStatic, @@ -54,7 +57,9 @@ func NewEmptyReplacer() *Replacer { // use NewReplacer to make one. type Replacer struct { providers []ReplacerFunc - static map[string]any + + static map[string]any + mapMutex *sync.RWMutex } // Map adds mapFunc to the list of value providers. @@ -65,7 +70,9 @@ func (r *Replacer) Map(mapFunc ReplacerFunc) { // Set sets a custom variable to a static value. func (r *Replacer) Set(variable string, value any) { + r.mapMutex.Lock() r.static[variable] = value + r.mapMutex.Unlock() } // Get gets a value from the replacer. It returns @@ -89,11 +96,15 @@ func (r *Replacer) GetString(variable string) (string, bool) { // Delete removes a variable with a static value // that was created using Set. func (r *Replacer) Delete(variable string) { + r.mapMutex.Lock() delete(r.static, variable) + r.mapMutex.Unlock() } // fromStatic provides values from r.static. func (r *Replacer) fromStatic(key string) (any, bool) { + r.mapMutex.RLock() + defer r.mapMutex.RUnlock() val, ok := r.static[key] return val, ok } diff --git a/replacer_test.go b/replacer_test.go index c88683947..d18ec8eea 100644 --- a/replacer_test.go +++ b/replacer_test.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "runtime" + "sync" "testing" ) @@ -238,6 +239,7 @@ func TestReplacerSet(t *testing.T) { func TestReplacerReplaceKnown(t *testing.T) { rep := Replacer{ + mapMutex: &sync.RWMutex{}, providers: []ReplacerFunc{ // split our possible vars to two functions (to test if both functions are called) func(key string) (val any, ok bool) { @@ -310,6 +312,7 @@ func TestReplacerReplaceKnown(t *testing.T) { func TestReplacerDelete(t *testing.T) { rep := Replacer{ + mapMutex: &sync.RWMutex{}, static: map[string]any{ "key1": "val1", "key2": "val2", @@ -463,5 +466,6 @@ func testReplacer() Replacer { return Replacer{ providers: make([]ReplacerFunc, 0), static: make(map[string]any), + mapMutex: &sync.RWMutex{}, } }