A go template renderer based on Perl's Template Toolkit
at main 2.6 kB view raw
1package gott 2 3import ( 4 "container/list" 5 "sync" 6) 7 8// cacheEntry holds a cached template AST 9type cacheEntry struct { 10 key string 11 tmpl *Template 12 element *list.Element // pointer to LRU list element 13} 14 15// astCache is a thread-safe LRU cache for parsed template ASTs 16type astCache struct { 17 mu sync.RWMutex 18 items map[string]*cacheEntry 19 lru *list.List // front = most recently used, back = least recently used 20 maxSize int // 0 = unlimited 21} 22 23// newCache creates a new LRU cache with the specified max size. 24// If maxSize is 0, the cache has no size limit. 25func newCache(maxSize int) *astCache { 26 return &astCache{ 27 items: make(map[string]*cacheEntry), 28 lru: list.New(), 29 maxSize: maxSize, 30 } 31} 32 33// Get retrieves a cached template by key. 34// Returns the template and true if found, nil and false otherwise. 35// Accessing an entry moves it to the front of the LRU list. 36func (c *astCache) Get(key string) (*Template, bool) { 37 c.mu.Lock() 38 defer c.mu.Unlock() 39 40 entry, ok := c.items[key] 41 if !ok { 42 return nil, false 43 } 44 45 // Move to front of LRU list (most recently used) 46 c.lru.MoveToFront(entry.element) 47 return entry.tmpl, true 48} 49 50// Put stores a template in the cache. 51// If the cache is at capacity, the least recently used entry is evicted. 52func (c *astCache) Put(key string, tmpl *Template) { 53 c.mu.Lock() 54 defer c.mu.Unlock() 55 56 // Check if key already exists 57 if entry, ok := c.items[key]; ok { 58 // Update existing entry 59 entry.tmpl = tmpl 60 c.lru.MoveToFront(entry.element) 61 return 62 } 63 64 // Evict LRU entry if at capacity 65 if c.maxSize > 0 && len(c.items) >= c.maxSize { 66 c.evictLRU() 67 } 68 69 // Create new entry 70 entry := &cacheEntry{ 71 key: key, 72 tmpl: tmpl, 73 } 74 entry.element = c.lru.PushFront(entry) 75 c.items[key] = entry 76} 77 78// evictLRU removes the least recently used entry. 79// Caller must hold the write lock. 80func (c *astCache) evictLRU() { 81 oldest := c.lru.Back() 82 if oldest == nil { 83 return 84 } 85 86 entry := oldest.Value.(*cacheEntry) 87 c.lru.Remove(oldest) 88 delete(c.items, entry.key) 89} 90 91// Clear removes all entries from the cache. 92func (c *astCache) Clear() { 93 c.mu.Lock() 94 defer c.mu.Unlock() 95 96 c.items = make(map[string]*cacheEntry) 97 c.lru.Init() 98} 99 100// Len returns the number of entries in the cache. 101func (c *astCache) Len() int { 102 c.mu.RLock() 103 defer c.mu.RUnlock() 104 return len(c.items) 105}