Initial QSfera import
This commit is contained in:
+92
@@ -0,0 +1,92 @@
|
||||
package option
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Set is a container to store multiple options. Because options are
|
||||
// usually used all over the place to configure various aspects of
|
||||
// a system, it is often useful to be able to collect multiple options
|
||||
// together and pass them around as a single entity.
|
||||
//
|
||||
// Note that Set is meant to be add-only; You usually do not remove
|
||||
// options from a Set.
|
||||
//
|
||||
// The intention is to create a set using a sync.Pool; we would like
|
||||
// to provide a centralized pool of Sets so that you don't need to
|
||||
// instantiate a new pool for every type of option you want to
|
||||
// store, but that is not quite possible because of the limitations
|
||||
// of parameterized types in Go. Instead create a `*option.SetPool`
|
||||
// with an appropriate type parameter and allocator.
|
||||
type Set[T Interface] struct {
|
||||
mu sync.RWMutex
|
||||
options []T
|
||||
}
|
||||
|
||||
func NewSet[T Interface]() *Set[T] {
|
||||
return &Set[T]{
|
||||
options: make([]T, 0, 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Set[T]) Add(opt T) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.options = append(s.options, opt)
|
||||
}
|
||||
|
||||
func (s *Set[T]) Reset() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.options = s.options[:0] // Reset the options slice to avoid memory leaks
|
||||
}
|
||||
|
||||
func (s *Set[T]) Len() int {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return len(s.options)
|
||||
}
|
||||
|
||||
func (s *Set[T]) Option(i int) T {
|
||||
var zero T
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
if i < 0 || i >= len(s.options) {
|
||||
return zero
|
||||
}
|
||||
return s.options[i]
|
||||
}
|
||||
|
||||
// List returns a slice of all options stored in the Set.
|
||||
// Note that the slice is the same slice that is used internally, so
|
||||
// you should not modify the contents of the slice directly.
|
||||
// This to avoid unnecessary allocations and copying of the slice for
|
||||
// performance reasons.
|
||||
func (s *Set[T]) List() []T {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return s.options
|
||||
}
|
||||
|
||||
// SetPool is a pool of Sets that can be used to efficiently manage
|
||||
// the lifecycle of Sets. It uses a sync.Pool to store and retrieve
|
||||
// Sets, allowing for efficient reuse of memory and reducing the
|
||||
// number of allocations required when creating new Sets.
|
||||
type SetPool[T Interface] struct {
|
||||
pool *sync.Pool // sync.Pool that contains *Set[T]
|
||||
}
|
||||
|
||||
func NewSetPool[T Interface](pool *sync.Pool) *SetPool[T] {
|
||||
return &SetPool[T]{
|
||||
pool: pool,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SetPool[T]) Get() *Set[T] {
|
||||
return p.pool.Get().(*Set[T])
|
||||
}
|
||||
|
||||
func (p *SetPool[T]) Put(s *Set[T]) {
|
||||
s.Reset()
|
||||
p.pool.Put(s)
|
||||
}
|
||||
Reference in New Issue
Block a user