blob: 269b4ab0cb4872bcf7347ccd6f373a6bd9847d0f [file] [log] [blame]
Holger Hildebrandtfa074992020-03-27 15:42:06 +00001/*
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 unsafePowerSet := set.s.PowerSet().(*threadUnsafeSet)
230 set.RUnlock()
231
232 ret := &threadSafeSet{s: newThreadUnsafeSet()}
233 for subset := range unsafePowerSet.Iter() {
234 unsafeSubset := subset.(*threadUnsafeSet)
235 ret.Add(&threadSafeSet{s: *unsafeSubset})
236 }
237 return ret
238}
239
240func (set *threadSafeSet) Pop() interface{} {
241 set.Lock()
242 defer set.Unlock()
243 return set.s.Pop()
244}
245
246func (set *threadSafeSet) CartesianProduct(other Set) Set {
247 o := other.(*threadSafeSet)
248
249 set.RLock()
250 o.RLock()
251
252 unsafeCartProduct := set.s.CartesianProduct(&o.s).(*threadUnsafeSet)
253 ret := &threadSafeSet{s: *unsafeCartProduct}
254 set.RUnlock()
255 o.RUnlock()
256 return ret
257}
258
259func (set *threadSafeSet) ToSlice() []interface{} {
260 keys := make([]interface{}, 0, set.Cardinality())
261 set.RLock()
262 for elem := range set.s {
263 keys = append(keys, elem)
264 }
265 set.RUnlock()
266 return keys
267}
268
269func (set *threadSafeSet) MarshalJSON() ([]byte, error) {
270 set.RLock()
271 b, err := set.s.MarshalJSON()
272 set.RUnlock()
273
274 return b, err
275}
276
277func (set *threadSafeSet) UnmarshalJSON(p []byte) error {
278 set.RLock()
279 err := set.s.UnmarshalJSON(p)
280 set.RUnlock()
281
282 return err
283}