set_ts.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package set
  2. import (
  3. "sync"
  4. )
  5. // Set defines a thread safe set data structure.
  6. type Set struct {
  7. set
  8. l sync.RWMutex // we name it because we don't want to expose it
  9. }
  10. // New creates and initialize a new Set. It's accept a variable number of
  11. // arguments to populate the initial set. If nothing passed a Set with zero
  12. // size is created.
  13. func New(items ...interface{}) *Set {
  14. s := &Set{}
  15. s.m = make(map[interface{}]struct{})
  16. // Ensure interface compliance
  17. var _ Interface = s
  18. s.Add(items...)
  19. return s
  20. }
  21. // New creates and initalizes a new Set interface. It accepts a variable
  22. // number of arguments to populate the initial set. If nothing is passed a
  23. // zero size Set based on the struct is created.
  24. func (s *Set) New(items ...interface{}) Interface {
  25. return New(items...)
  26. }
  27. // Add includes the specified items (one or more) to the set. The underlying
  28. // Set s is modified. If passed nothing it silently returns.
  29. func (s *Set) Add(items ...interface{}) {
  30. if len(items) == 0 {
  31. return
  32. }
  33. s.l.Lock()
  34. defer s.l.Unlock()
  35. for _, item := range items {
  36. s.m[item] = keyExists
  37. }
  38. }
  39. // Remove deletes the specified items from the set. The underlying Set s is
  40. // modified. If passed nothing it silently returns.
  41. func (s *Set) Remove(items ...interface{}) {
  42. if len(items) == 0 {
  43. return
  44. }
  45. s.l.Lock()
  46. defer s.l.Unlock()
  47. for _, item := range items {
  48. delete(s.m, item)
  49. }
  50. }
  51. // Pop deletes and return an item from the set. The underlying Set s is
  52. // modified. If set is empty, nil is returned.
  53. func (s *Set) Pop() interface{} {
  54. s.l.RLock()
  55. for item := range s.m {
  56. s.l.RUnlock()
  57. s.l.Lock()
  58. delete(s.m, item)
  59. s.l.Unlock()
  60. return item
  61. }
  62. s.l.RUnlock()
  63. return nil
  64. }
  65. // Has looks for the existence of items passed. It returns false if nothing is
  66. // passed. For multiple items it returns true only if all of the items exist.
  67. func (s *Set) Has(items ...interface{}) bool {
  68. // assume checked for empty item, which not exist
  69. if len(items) == 0 {
  70. return false
  71. }
  72. s.l.RLock()
  73. defer s.l.RUnlock()
  74. has := true
  75. for _, item := range items {
  76. if _, has = s.m[item]; !has {
  77. break
  78. }
  79. }
  80. return has
  81. }
  82. // Size returns the number of items in a set.
  83. func (s *Set) Size() int {
  84. s.l.RLock()
  85. defer s.l.RUnlock()
  86. l := len(s.m)
  87. return l
  88. }
  89. // Clear removes all items from the set.
  90. func (s *Set) Clear() {
  91. s.l.Lock()
  92. defer s.l.Unlock()
  93. s.m = make(map[interface{}]struct{})
  94. }
  95. // IsEqual test whether s and t are the same in size and have the same items.
  96. func (s *Set) IsEqual(t Interface) bool {
  97. s.l.RLock()
  98. defer s.l.RUnlock()
  99. // Force locking only if given set is threadsafe.
  100. if conv, ok := t.(*Set); ok {
  101. conv.l.RLock()
  102. defer conv.l.RUnlock()
  103. }
  104. // return false if they are no the same size
  105. if sameSize := len(s.m) == t.Size(); !sameSize {
  106. return false
  107. }
  108. equal := true
  109. t.Each(func(item interface{}) bool {
  110. _, equal = s.m[item]
  111. return equal // if false, Each() will end
  112. })
  113. return equal
  114. }
  115. // IsSubset tests whether t is a subset of s.
  116. func (s *Set) IsSubset(t Interface) (subset bool) {
  117. s.l.RLock()
  118. defer s.l.RUnlock()
  119. subset = true
  120. t.Each(func(item interface{}) bool {
  121. _, subset = s.m[item]
  122. return subset
  123. })
  124. return
  125. }
  126. // Each traverses the items in the Set, calling the provided function for each
  127. // set member. Traversal will continue until all items in the Set have been
  128. // visited, or if the closure returns false.
  129. func (s *Set) Each(f func(item interface{}) bool) {
  130. s.l.RLock()
  131. defer s.l.RUnlock()
  132. for item := range s.m {
  133. if !f(item) {
  134. break
  135. }
  136. }
  137. }
  138. // List returns a slice of all items. There is also StringSlice() and
  139. // IntSlice() methods for returning slices of type string or int.
  140. func (s *Set) List() []interface{} {
  141. s.l.RLock()
  142. defer s.l.RUnlock()
  143. list := make([]interface{}, 0, len(s.m))
  144. for item := range s.m {
  145. list = append(list, item)
  146. }
  147. return list
  148. }
  149. // Copy returns a new Set with a copy of s.
  150. func (s *Set) Copy() Interface {
  151. return New(s.List()...)
  152. }
  153. // Merge is like Union, however it modifies the current set it's applied on
  154. // with the given t set.
  155. func (s *Set) Merge(t Interface) {
  156. s.l.Lock()
  157. defer s.l.Unlock()
  158. t.Each(func(item interface{}) bool {
  159. s.m[item] = keyExists
  160. return true
  161. })
  162. }