on main help sign in
refactor: use csync.Map for regex caches (#2187)

* refactor: use csync.Map for regex caches Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: lint Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * ci: golangci-lint 2.9 Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> --------- Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>

commit7f3d7c756d4bc289c45ccb23e2a8a9c1c2e21b0b authorCarlos Alexandro Becker <caarlos0@users.noreply.github.com> dateWed 11 Feb 2026, 09:03 (8 months ago) parent0ed5806
1 file changed+13−36
internal/agent/tools/grep.go+13−36
internal/agent/tools/grep.go+13−36
@@ -15,64 +15,41 @@ import (
1515 "regexp"
1616 "sort"
1717 "strings"
18− "sync"
1918 "time"
2019
2120 "charm.land/fantasy"
21+ "github.com/charmbracelet/crush/internal/csync"
2222 "github.com/charmbracelet/crush/internal/fsext"
2323)
2424
2525// regexCache provides thread-safe caching of compiled regex patterns
2626type regexCache struct {
27− cache map[string]*regexp.Regexp
28− mu sync.RWMutex
27+ *csync.Map[string, *regexp.Regexp]
2928}
3029
3130// newRegexCache creates a new regex cache
3231func newRegexCache() *regexCache {
3332 return &regexCache{
34− cache: make(map[string]*regexp.Regexp),
33+ Map: csync.NewMap[string, *regexp.Regexp](),
3534 }
3635}
3736
3837// get retrieves a compiled regex from cache or compiles and caches it
3938func (rc *regexCache) get(pattern string) (*regexp.Regexp, error) {
40− // Try to get from cache first (read lock)
41− rc.mu.RLock()
42− if regex, exists := rc.cache[pattern]; exists {
43− rc.mu.RUnlock()
44− return regex, nil
45− }
46− rc.mu.RUnlock()
47−
48− // Compile the regex (write lock)
49− rc.mu.Lock()
50− defer rc.mu.Unlock()
51−
52− // Double-check in case another goroutine compiled it while we waited
53− if regex, exists := rc.cache[pattern]; exists {
54− return regex, nil
55− }
56−
57− // Compile and cache the regex
58− regex, err := regexp.Compile(pattern)
59− if err != nil {
60− return nil, err
61− }
62−
63− rc.cache[pattern] = regex
64− return regex, nil
39+ var rerr error
40+ return rc.GetOrSet(pattern, func() *regexp.Regexp {
41+ regex, err := regexp.Compile(pattern)
42+ if err != nil {
43+ rerr = err
44+ }
45+ return regex
46+ }), rerr
6547}
6648
6749// ResetCache clears compiled regex caches to prevent unbounded growth across sessions.
6850func ResetCache() {
69− searchRegexCache.mu.Lock()
70− clear(searchRegexCache.cache)
71− searchRegexCache.mu.Unlock()
72−
73− globRegexCache.mu.Lock()
74− clear(globRegexCache.cache)
75− globRegexCache.mu.Unlock()
51+ searchRegexCache.Reset(map[string]*regexp.Regexp{})
52+ globRegexCache.Reset(map[string]*regexp.Regexp{})
7653}
7754
7855// Global regex cache instances