76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
package project
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/collections"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tsoptions"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tspath"
|
|
"github.com/zeebo/xxh3"
|
|
)
|
|
|
|
type extendedConfigCache struct {
|
|
entries collections.SyncMap[tspath.Path, *extendedConfigCacheEntry]
|
|
}
|
|
|
|
type extendedConfigCacheEntry struct {
|
|
mu sync.Mutex
|
|
entry *tsoptions.ExtendedConfigCacheEntry
|
|
hash xxh3.Uint128
|
|
refCount int
|
|
}
|
|
|
|
func (c *extendedConfigCache) Acquire(fh FileHandle, path tspath.Path, parse func() *tsoptions.ExtendedConfigCacheEntry) *tsoptions.ExtendedConfigCacheEntry {
|
|
entry, loaded := c.loadOrStoreNewLockedEntry(path)
|
|
defer entry.mu.Unlock()
|
|
var hash xxh3.Uint128
|
|
if fh != nil {
|
|
hash = fh.Hash()
|
|
}
|
|
if !loaded || entry.hash != hash {
|
|
// Reparse the config if the hash has changed, or parse for the first time.
|
|
entry.entry = parse()
|
|
entry.hash = hash
|
|
}
|
|
return entry.entry
|
|
}
|
|
|
|
func (c *extendedConfigCache) Ref(path tspath.Path) {
|
|
if entry, ok := c.entries.Load(path); ok {
|
|
entry.mu.Lock()
|
|
entry.refCount++
|
|
entry.mu.Unlock()
|
|
}
|
|
}
|
|
|
|
func (c *extendedConfigCache) Deref(path tspath.Path) {
|
|
if entry, ok := c.entries.Load(path); ok {
|
|
entry.mu.Lock()
|
|
entry.refCount--
|
|
remove := entry.refCount <= 0
|
|
entry.mu.Unlock()
|
|
if remove {
|
|
c.entries.Delete(path)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *extendedConfigCache) Has(path tspath.Path) bool {
|
|
_, ok := c.entries.Load(path)
|
|
return ok
|
|
}
|
|
|
|
// loadOrStoreNewLockedEntry loads an existing entry or creates a new one. The returned
|
|
// entry's mutex is locked and its refCount is incremented (or initialized to 1
|
|
// in the case of a new entry).
|
|
func (c *extendedConfigCache) loadOrStoreNewLockedEntry(path tspath.Path) (*extendedConfigCacheEntry, bool) {
|
|
entry := &extendedConfigCacheEntry{refCount: 1}
|
|
entry.mu.Lock()
|
|
if existing, loaded := c.entries.LoadOrStore(path, entry); loaded {
|
|
existing.mu.Lock()
|
|
existing.refCount++
|
|
return existing, true
|
|
}
|
|
return entry, false
|
|
}
|