set_ts.go 3.9 KB

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