slices.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package csync
  2. import (
  3. "iter"
  4. "sync"
  5. )
  6. // LazySlice is a thread-safe lazy-loaded slice.
  7. type LazySlice[K any] struct {
  8. inner []K
  9. wg sync.WaitGroup
  10. }
  11. // NewLazySlice creates a new slice and runs the [load] function in a goroutine
  12. // to populate it.
  13. func NewLazySlice[K any](load func() []K) *LazySlice[K] {
  14. s := &LazySlice[K]{}
  15. s.wg.Go(func() {
  16. s.inner = load()
  17. })
  18. return s
  19. }
  20. // Seq returns an iterator that yields elements from the slice.
  21. func (s *LazySlice[K]) Seq() iter.Seq[K] {
  22. s.wg.Wait()
  23. return func(yield func(K) bool) {
  24. for _, v := range s.inner {
  25. if !yield(v) {
  26. return
  27. }
  28. }
  29. }
  30. }
  31. // Slice is a thread-safe slice implementation that provides concurrent access.
  32. type Slice[T any] struct {
  33. inner []T
  34. mu sync.RWMutex
  35. }
  36. // NewSlice creates a new thread-safe slice.
  37. func NewSlice[T any]() *Slice[T] {
  38. return &Slice[T]{
  39. inner: make([]T, 0),
  40. }
  41. }
  42. // NewSliceFrom creates a new thread-safe slice from an existing slice.
  43. func NewSliceFrom[T any](s []T) *Slice[T] {
  44. inner := make([]T, len(s))
  45. copy(inner, s)
  46. return &Slice[T]{
  47. inner: inner,
  48. }
  49. }
  50. // Append adds an element to the end of the slice.
  51. func (s *Slice[T]) Append(items ...T) {
  52. s.mu.Lock()
  53. defer s.mu.Unlock()
  54. s.inner = append(s.inner, items...)
  55. }
  56. // Get returns the element at the specified index.
  57. func (s *Slice[T]) Get(index int) (T, bool) {
  58. s.mu.RLock()
  59. defer s.mu.RUnlock()
  60. var zero T
  61. if index < 0 || index >= len(s.inner) {
  62. return zero, false
  63. }
  64. return s.inner[index], true
  65. }
  66. // Len returns the number of elements in the slice.
  67. func (s *Slice[T]) Len() int {
  68. s.mu.RLock()
  69. defer s.mu.RUnlock()
  70. return len(s.inner)
  71. }
  72. // SetSlice replaces the entire slice with a new one.
  73. func (s *Slice[T]) SetSlice(items []T) {
  74. s.mu.Lock()
  75. defer s.mu.Unlock()
  76. s.inner = make([]T, len(items))
  77. copy(s.inner, items)
  78. }
  79. // Seq returns an iterator that yields elements from the slice.
  80. func (s *Slice[T]) Seq() iter.Seq[T] {
  81. return func(yield func(T) bool) {
  82. for _, v := range s.Seq2() {
  83. if !yield(v) {
  84. return
  85. }
  86. }
  87. }
  88. }
  89. // Seq2 returns an iterator that yields index-value pairs from the slice.
  90. func (s *Slice[T]) Seq2() iter.Seq2[int, T] {
  91. items := s.Copy()
  92. return func(yield func(int, T) bool) {
  93. for i, v := range items {
  94. if !yield(i, v) {
  95. return
  96. }
  97. }
  98. }
  99. }
  100. // Copy returns a copy of the inner slice.
  101. func (s *Slice[T]) Copy() []T {
  102. s.mu.RLock()
  103. defer s.mu.RUnlock()
  104. items := make([]T, len(s.inner))
  105. copy(items, s.inner)
  106. return items
  107. }