Skip to content

Instantly share code, notes, and snippets.

@shehackedyou
Last active March 6, 2025 13:13
Show Gist options
  • Select an option

  • Save shehackedyou/e992a3dbee34387e77229600a4d5f77c to your computer and use it in GitHub Desktop.

Select an option

Save shehackedyou/e992a3dbee34387e77229600a4d5f77c to your computer and use it in GitHub Desktop.
package ringmap
import (
"sync"
"container/ring"
)
type RingMapCache struct {
cacheMap map[string]interface{}
keyRingBuffer *ring.Ring
mutex sync.RWMutex
capacity int
}
func newKeyRing(capacity int) *ring.Ring {
return ring.New(capacity)
}
func NewRingMapCache(capacity int) *RingMapCache {
return &RingMapCache{
cacheMap: make(map[string]interface{}, capacity),
keyRingBuffer: newKeyRing(capacity),
mutex: sync.RWMutex{},
capacity: capacity,
}
}
func (c *RingMapCache) Get(key string) (interface{}, bool) {
c.mutex.RLock()
defer c.mutex.RUnlock()
value, found := c.cacheMap[key]
return value, found
}
func (c *RingMapCache) Set(key string, value interface{}) {
c.mutex.Lock()
defer c.mutex.Unlock()
_, found := c.cacheMap[key]
if found {
c.cacheMap[key] = value
return
}
if c.keyRingBuffer.Len() == c.capacity {
oldestKeyRing := c.keyRingBuffer.Prev()
if oldestKeyRing != c.keyRingBuffer {
oldestKey := oldestKeyRing.Value.(string)
delete(c.cacheMap, oldestKey)
c.keyRingBuffer.Unlink(1)
}
}
c.cacheMap[key] = value
c.keyRingBuffer.Value = key
c.keyRingBuffer.Move(1)
}
func (c *RingMapCache) Len() int {
c.mutex.RLock()
defer c.mutex.RUnlock()
return c.keyRingBuffer.Len()
}
func (c *RingMapCache) Cap() int {
return c.capacity
}
func (c *RingMapCache) Clear() {
c.mutex.Lock()
defer c.mutex.Unlock()
c.cacheMap = make(map[string]interface{}, c.capacity)
c.keyRingBuffer = newKeyRing(c.capacity)
}
func (c *RingMapCache) Head() string {
c.mutex.RLock()
defer c.mutex.RUnlock()
if c.keyRingBuffer.Len() == 0 {
return ""
}
return c.keyRingBuffer.Prev().Value.(string)
}
func (c *RingMapCache) Tail() string {
c.mutex.RLock()
defer c.mutex.RUnlock()
if c.keyRingBuffer.Len() == 0 {
return ""
}
return c.keyRingBuffer.Value.(string)
}
func (c *RingMapCache) Keys() []string {
c.mutex.RLock()
defer c.mutex.RUnlock()
keys := make([]string, 0, c.keyRingBuffer.Len())
c.keyRingBuffer.Do(func(v interface{}) {
if v != nil {
keys = append(keys, v.(string))
}
})
return keys
}
func (c *RingMapCache) Dequeue() (string, interface{}, bool) {
c.mutex.Lock()
defer c.mutex.Unlock()
oldestKeyRing := c.keyRingBuffer.Prev()
if oldestKeyRing == c.keyRingBuffer || oldestKeyRing.Value == nil {
return "", nil, false // Cache empty
}
oldestKey := oldestKeyRing.Value.(string)
value, found := c.cacheMap[oldestKey]
if found {
delete(c.cacheMap, oldestKey)
c.keyRingBuffer.Unlink(1)
return oldestKey, value, true
}
return oldestKey, nil, false // Key not found in map (unlikely)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment