1/* 2Open Source Initiative OSI - The MIT License (MIT):Licensing 3 4The MIT License (MIT) 5Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com) 6 7Permission is hereby granted, free of charge, to any person obtaining a copy of 8this software and associated documentation files (the "Software"), to deal in 9the Software without restriction, including without limitation the rights to 10use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11of the Software, and to permit persons to whom the Software is furnished to do 12so, subject to the following conditions: 13 14The above copyright notice and this permission notice shall be included in all 15copies or substantial portions of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23SOFTWARE. 24*/ 25 26package mapset 27 28import "sync" 29 30type threadSafeSet struct { 31 s threadUnsafeSet 32 sync.RWMutex 33} 34 35func newThreadSafeSet() threadSafeSet { 36 return threadSafeSet{s: newThreadUnsafeSet()} 37} 38 39func (set *threadSafeSet) Add(i interface{}) bool { 40 set.Lock() 41 ret := set.s.Add(i) 42 set.Unlock() 43 return ret 44} 45 46func (set *threadSafeSet) Contains(i ...interface{}) bool { 47 set.RLock() 48 ret := set.s.Contains(i...) 49 set.RUnlock() 50 return ret 51} 52 53func (set *threadSafeSet) IsSubset(other Set) bool { 54 o := other.(*threadSafeSet) 55 56 set.RLock() 57 o.RLock() 58 59 ret := set.s.IsSubset(&o.s) 60 set.RUnlock() 61 o.RUnlock() 62 return ret 63} 64 65func (set *threadSafeSet) IsProperSubset(other Set) bool { 66 o := other.(*threadSafeSet) 67 68 set.RLock() 69 defer set.RUnlock() 70 o.RLock() 71 defer o.RUnlock() 72 73 return set.s.IsProperSubset(&o.s) 74} 75 76func (set *threadSafeSet) IsSuperset(other Set) bool { 77 return other.IsSubset(set) 78} 79 80func (set *threadSafeSet) IsProperSuperset(other Set) bool { 81 return other.IsProperSubset(set) 82} 83 84func (set *threadSafeSet) Union(other Set) Set { 85 o := other.(*threadSafeSet) 86 87 set.RLock() 88 o.RLock() 89 90 unsafeUnion := set.s.Union(&o.s).(*threadUnsafeSet) 91 ret := &threadSafeSet{s: *unsafeUnion} 92 set.RUnlock() 93 o.RUnlock() 94 return ret 95} 96 97func (set *threadSafeSet) Intersect(other Set) Set { 98 o := other.(*threadSafeSet) 99 100 set.RLock() 101 o.RLock() 102 103 unsafeIntersection := set.s.Intersect(&o.s).(*threadUnsafeSet) 104 ret := &threadSafeSet{s: *unsafeIntersection} 105 set.RUnlock() 106 o.RUnlock() 107 return ret 108} 109 110func (set *threadSafeSet) Difference(other Set) Set { 111 o := other.(*threadSafeSet) 112 113 set.RLock() 114 o.RLock() 115 116 unsafeDifference := set.s.Difference(&o.s).(*threadUnsafeSet) 117 ret := &threadSafeSet{s: *unsafeDifference} 118 set.RUnlock() 119 o.RUnlock() 120 return ret 121} 122 123func (set *threadSafeSet) SymmetricDifference(other Set) Set { 124 o := other.(*threadSafeSet) 125 126 set.RLock() 127 o.RLock() 128 129 unsafeDifference := set.s.SymmetricDifference(&o.s).(*threadUnsafeSet) 130 ret := &threadSafeSet{s: *unsafeDifference} 131 set.RUnlock() 132 o.RUnlock() 133 return ret 134} 135 136func (set *threadSafeSet) Clear() { 137 set.Lock() 138 set.s = newThreadUnsafeSet() 139 set.Unlock() 140} 141 142func (set *threadSafeSet) Remove(i interface{}) { 143 set.Lock() 144 delete(set.s, i) 145 set.Unlock() 146} 147 148func (set *threadSafeSet) Cardinality() int { 149 set.RLock() 150 defer set.RUnlock() 151 return len(set.s) 152} 153 154func (set *threadSafeSet) Each(cb func(interface{}) bool) { 155 set.RLock() 156 for elem := range set.s { 157 if cb(elem) { 158 break 159 } 160 } 161 set.RUnlock() 162} 163 164func (set *threadSafeSet) Iter() <-chan interface{} { 165 ch := make(chan interface{}) 166 go func() { 167 set.RLock() 168 169 for elem := range set.s { 170 ch <- elem 171 } 172 close(ch) 173 set.RUnlock() 174 }() 175 176 return ch 177} 178 179func (set *threadSafeSet) Iterator() *Iterator { 180 iterator, ch, stopCh := newIterator() 181 182 go func() { 183 set.RLock() 184 L: 185 for elem := range set.s { 186 select { 187 case <-stopCh: 188 break L 189 case ch <- elem: 190 } 191 } 192 close(ch) 193 set.RUnlock() 194 }() 195 196 return iterator 197} 198 199func (set *threadSafeSet) Equal(other Set) bool { 200 o := other.(*threadSafeSet) 201 202 set.RLock() 203 o.RLock() 204 205 ret := set.s.Equal(&o.s) 206 set.RUnlock() 207 o.RUnlock() 208 return ret 209} 210 211func (set *threadSafeSet) Clone() Set { 212 set.RLock() 213 214 unsafeClone := set.s.Clone().(*threadUnsafeSet) 215 ret := &threadSafeSet{s: *unsafeClone} 216 set.RUnlock() 217 return ret 218} 219 220func (set *threadSafeSet) String() string { 221 set.RLock() 222 ret := set.s.String() 223 set.RUnlock() 224 return ret 225} 226 227func (set *threadSafeSet) PowerSet() Set { 228 set.RLock() 229 ret := set.s.PowerSet() 230 set.RUnlock() 231 return ret 232} 233 234func (set *threadSafeSet) Pop() interface{} { 235 set.Lock() 236 defer set.Unlock() 237 return set.s.Pop() 238} 239 240func (set *threadSafeSet) CartesianProduct(other Set) Set { 241 o := other.(*threadSafeSet) 242 243 set.RLock() 244 o.RLock() 245 246 unsafeCartProduct := set.s.CartesianProduct(&o.s).(*threadUnsafeSet) 247 ret := &threadSafeSet{s: *unsafeCartProduct} 248 set.RUnlock() 249 o.RUnlock() 250 return ret 251} 252 253func (set *threadSafeSet) ToSlice() []interface{} { 254 keys := make([]interface{}, 0, set.Cardinality()) 255 set.RLock() 256 for elem := range set.s { 257 keys = append(keys, elem) 258 } 259 set.RUnlock() 260 return keys 261} 262 263func (set *threadSafeSet) MarshalJSON() ([]byte, error) { 264 set.RLock() 265 b, err := set.s.MarshalJSON() 266 set.RUnlock() 267 268 return b, err 269} 270 271func (set *threadSafeSet) UnmarshalJSON(p []byte) error { 272 set.RLock() 273 err := set.s.UnmarshalJSON(p) 274 set.RUnlock() 275 276 return err 277} 278