package session import ( "context" "sync" "time" ) type cache_stage[T any] struct { cache map[storagekey]T deleted map[storagekey]T } func make_cache_stage[T any]() *cache_stage[T] { return &cache_stage[T]{ cache: make(map[storagekey]T), deleted: make(map[storagekey]T), } } type consumer_common[T any] struct { lock sync.Mutex ttl time.Duration ctx context.Context stages [2]*cache_stage[T] startTime time.Time onSessionInvalidated []func(InvalidatedSession) } func (c *consumer_common[T]) add_internal(sk storagekey, si T) { c.stages[0].cache[sk] = si delete(c.stages[0].deleted, sk) c.stages[1].cache[sk] = si delete(c.stages[1].deleted, sk) } func (c *consumer_common[T]) delete_internal(sk storagekey) (old T) { if v, ok := c.stages[0].cache[sk]; ok { old = v c.stages[0].deleted[sk] = old c.stages[1].deleted[sk] = old delete(c.stages[0].cache, sk) delete(c.stages[1].cache, sk) } else if v, ok = c.stages[1].cache[sk]; ok { old = v c.stages[1].deleted[sk] = old delete(c.stages[1].cache, sk) } return } func (c *consumer_common[T]) delete(sk storagekey) T { c.lock.Lock() defer c.lock.Unlock() return c.delete_internal(sk) } func (c *consumer_common[T]) changeStage() { c.lock.Lock() defer c.lock.Unlock() c.stages[1] = c.stages[0] c.stages[0] = make_cache_stage[T]() }