set.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2015 The etcd Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package types
  15. import (
  16. "reflect"
  17. "sort"
  18. "sync"
  19. )
  20. type Set interface {
  21. Add(string)
  22. Remove(string)
  23. Contains(string) bool
  24. Equals(Set) bool
  25. Length() int
  26. Values() []string
  27. Copy() Set
  28. Sub(Set) Set
  29. }
  30. func NewUnsafeSet(values ...string) *unsafeSet {
  31. set := &unsafeSet{make(map[string]struct{})}
  32. for _, v := range values {
  33. set.Add(v)
  34. }
  35. return set
  36. }
  37. func NewThreadsafeSet(values ...string) *tsafeSet {
  38. us := NewUnsafeSet(values...)
  39. return &tsafeSet{us, sync.RWMutex{}}
  40. }
  41. type unsafeSet struct {
  42. d map[string]struct{}
  43. }
  44. // Add adds a new value to the set (no-op if the value is already present)
  45. func (us *unsafeSet) Add(value string) {
  46. us.d[value] = struct{}{}
  47. }
  48. // Remove removes the given value from the set
  49. func (us *unsafeSet) Remove(value string) {
  50. delete(us.d, value)
  51. }
  52. // Contains returns whether the set contains the given value
  53. func (us *unsafeSet) Contains(value string) (exists bool) {
  54. _, exists = us.d[value]
  55. return exists
  56. }
  57. // ContainsAll returns whether the set contains all given values
  58. func (us *unsafeSet) ContainsAll(values []string) bool {
  59. for _, s := range values {
  60. if !us.Contains(s) {
  61. return false
  62. }
  63. }
  64. return true
  65. }
  66. // Equals returns whether the contents of two sets are identical
  67. func (us *unsafeSet) Equals(other Set) bool {
  68. v1 := sort.StringSlice(us.Values())
  69. v2 := sort.StringSlice(other.Values())
  70. v1.Sort()
  71. v2.Sort()
  72. return reflect.DeepEqual(v1, v2)
  73. }
  74. // Length returns the number of elements in the set
  75. func (us *unsafeSet) Length() int {
  76. return len(us.d)
  77. }
  78. // Values returns the values of the Set in an unspecified order.
  79. func (us *unsafeSet) Values() (values []string) {
  80. values = make([]string, 0)
  81. for val := range us.d {
  82. values = append(values, val)
  83. }
  84. return values
  85. }
  86. // Copy creates a new Set containing the values of the first
  87. func (us *unsafeSet) Copy() Set {
  88. cp := NewUnsafeSet()
  89. for val := range us.d {
  90. cp.Add(val)
  91. }
  92. return cp
  93. }
  94. // Sub removes all elements in other from the set
  95. func (us *unsafeSet) Sub(other Set) Set {
  96. oValues := other.Values()
  97. result := us.Copy().(*unsafeSet)
  98. for _, val := range oValues {
  99. if _, ok := result.d[val]; !ok {
  100. continue
  101. }
  102. delete(result.d, val)
  103. }
  104. return result
  105. }
  106. type tsafeSet struct {
  107. us *unsafeSet
  108. m sync.RWMutex
  109. }
  110. func (ts *tsafeSet) Add(value string) {
  111. ts.m.Lock()
  112. defer ts.m.Unlock()
  113. ts.us.Add(value)
  114. }
  115. func (ts *tsafeSet) Remove(value string) {
  116. ts.m.Lock()
  117. defer ts.m.Unlock()
  118. ts.us.Remove(value)
  119. }
  120. func (ts *tsafeSet) Contains(value string) (exists bool) {
  121. ts.m.RLock()
  122. defer ts.m.RUnlock()
  123. return ts.us.Contains(value)
  124. }
  125. func (ts *tsafeSet) Equals(other Set) bool {
  126. ts.m.RLock()
  127. defer ts.m.RUnlock()
  128. // If ts and other represent the same variable, avoid calling
  129. // ts.us.Equals(other), to avoid double RLock bug
  130. if _other, ok := other.(*tsafeSet); ok {
  131. if _other == ts {
  132. return true
  133. }
  134. }
  135. return ts.us.Equals(other)
  136. }
  137. func (ts *tsafeSet) Length() int {
  138. ts.m.RLock()
  139. defer ts.m.RUnlock()
  140. return ts.us.Length()
  141. }
  142. func (ts *tsafeSet) Values() (values []string) {
  143. ts.m.RLock()
  144. defer ts.m.RUnlock()
  145. return ts.us.Values()
  146. }
  147. func (ts *tsafeSet) Copy() Set {
  148. ts.m.RLock()
  149. defer ts.m.RUnlock()
  150. usResult := ts.us.Copy().(*unsafeSet)
  151. return &tsafeSet{usResult, sync.RWMutex{}}
  152. }
  153. func (ts *tsafeSet) Sub(other Set) Set {
  154. ts.m.RLock()
  155. defer ts.m.RUnlock()
  156. // If ts and other represent the same variable, avoid calling
  157. // ts.us.Sub(other), to avoid double RLock bug
  158. if _other, ok := other.(*tsafeSet); ok {
  159. if _other == ts {
  160. usResult := NewUnsafeSet()
  161. return &tsafeSet{usResult, sync.RWMutex{}}
  162. }
  163. }
  164. usResult := ts.us.Sub(other).(*unsafeSet)
  165. return &tsafeSet{usResult, sync.RWMutex{}}
  166. }