slices.go 3.0 KB

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