package dataext import "sync" type SyncRingSet[TData comparable] struct { data map[TData]bool lock sync.Mutex ring *RingBuffer[TData] } func NewSyncRingSet[TData comparable](capacity int) *SyncRingSet[TData] { return &SyncRingSet[TData]{ data: make(map[TData]bool, capacity+1), lock: sync.Mutex{}, ring: NewRingBuffer[TData](capacity), } } // Add adds `value` to the set // returns true if the value was actually inserted (value did not exist beforehand) // returns false if the value already existed func (s *SyncRingSet[TData]) Add(value TData) bool { s.lock.Lock() defer s.lock.Unlock() if s.data == nil { s.data = make(map[TData]bool) } _, existsInPreState := s.data[value] if existsInPreState { return false } prev := s.ring.PushPop(value) s.data[value] = true if prev != nil { delete(s.data, *prev) } return true } func (s *SyncRingSet[TData]) AddAll(values []TData) { s.lock.Lock() defer s.lock.Unlock() if s.data == nil { s.data = make(map[TData]bool) } for _, value := range values { _, existsInPreState := s.data[value] if existsInPreState { continue } prev := s.ring.PushPop(value) s.data[value] = true if prev != nil { delete(s.data, *prev) } } } func (s *SyncRingSet[TData]) Remove(value TData) bool { s.lock.Lock() defer s.lock.Unlock() if s.data == nil { s.data = make(map[TData]bool) } _, existsInPreState := s.data[value] if !existsInPreState { return false } delete(s.data, value) s.ring.Remove(func(v TData) bool { return value == v }) return true } func (s *SyncRingSet[TData]) RemoveAll(values []TData) { s.lock.Lock() defer s.lock.Unlock() if s.data == nil { s.data = make(map[TData]bool) } for _, value := range values { delete(s.data, value) s.ring.Remove(func(v TData) bool { return value == v }) } } func (s *SyncRingSet[TData]) Contains(value TData) bool { s.lock.Lock() defer s.lock.Unlock() if s.data == nil { s.data = make(map[TData]bool) } _, ok := s.data[value] return ok } func (s *SyncRingSet[TData]) Get() []TData { s.lock.Lock() defer s.lock.Unlock() if s.data == nil { s.data = make(map[TData]bool) } r := make([]TData, 0, len(s.data)) for k := range s.data { r = append(r, k) } return r } // AddIfNotContains // returns true if the value was actually added (value did not exist beforehand) // returns false if the value already existed func (s *SyncRingSet[TData]) AddIfNotContains(key TData) bool { return s.Add(key) } // RemoveIfContains // returns true if the value was actually removed (value did exist beforehand) // returns false if the value did not exist in the set func (s *SyncRingSet[TData]) RemoveIfContains(key TData) bool { return s.Remove(key) }