github.com/sandwich-go/boost@v1.3.29/xcontainer/templates/sset/sset.go (about) 1 // sset 包提供了多种类型的集合 2 // 可以产生一个带读写锁的线程安全的SyncSet,也可以产生一个非线程安全的SyncSet 3 // New 产生非协程安全的版本 4 // NewSync 产生协程安全的版本 5 package sset 6 7 import ( 8 "sync" 9 ) 10 11 //template type SyncSet(VType) 12 13 type VType interface{} 14 15 // SyncSet 包含一个读写锁和一个map,根据不同需求可提供对切片协程安全版本或者非协程安全版本的实例 16 type SyncSet struct { 17 mu *localRWMutexVType 18 data map[VType]struct{} 19 } 20 21 // New 创建非协程安全版本 22 func New() *SyncSet { return newWithSafe(false) } 23 24 // NewSync 创建协程安全版本 25 func NewSync() *SyncSet { return newWithSafe(true) } 26 27 func newWithSafe(safe bool) *SyncSet { 28 return &SyncSet{data: make(map[VType]struct{}), mu: newLocalRWMutexVType(safe)} 29 } 30 31 // Iterator 遍历 32 func (set *SyncSet) Iterator(f func(v VType) bool) { 33 set.mu.RLock() 34 defer set.mu.RUnlock() 35 for k := range set.data { 36 if !f(k) { 37 break 38 } 39 } 40 } 41 42 // Add 添加元素 43 func (set *SyncSet) Add(items ...VType) { 44 set.mu.Lock() 45 if set.data == nil { 46 set.data = make(map[VType]struct{}) 47 } 48 for _, v := range items { 49 set.data[v] = struct{}{} 50 } 51 set.mu.Unlock() 52 } 53 54 // AddIfNotExist 如果元素不存在则添加,如添加成功则返回true 55 func (set *SyncSet) AddIfNotExist(item VType) (addOK bool) { 56 if !set.Contains(item) { 57 set.mu.Lock() 58 defer set.mu.Unlock() 59 if set.data == nil { 60 set.data = make(map[VType]struct{}) 61 } 62 if _, ok := set.data[item]; !ok { 63 set.data[item] = struct{}{} 64 return true 65 } 66 } 67 return false 68 } 69 70 // AddIfNotExistFunc 如果元素不存在且f返回true则添加,如添加成功则返回true 71 // f函数运行在lock之外 72 func (set *SyncSet) AddIfNotExistFunc(item VType, f func() bool) bool { 73 if !set.Contains(item) { 74 if f() { 75 set.mu.Lock() 76 defer set.mu.Unlock() 77 if set.data == nil { 78 set.data = make(map[VType]struct{}) 79 } 80 if _, ok := set.data[item]; !ok { 81 set.data[item] = struct{}{} 82 return true 83 } 84 } 85 } 86 return false 87 } 88 89 // AddIfNotExistFuncLock 如果元素不存在且f返回true则添加,如添加成功则返回true 90 // f函数运行在lock之内 91 func (set *SyncSet) AddIfNotExistFuncLock(item VType, f func() bool) bool { 92 if !set.Contains(item) { 93 set.mu.Lock() 94 defer set.mu.Unlock() 95 if set.data == nil { 96 set.data = make(map[VType]struct{}) 97 } 98 if f() { 99 if _, ok := set.data[item]; !ok { 100 set.data[item] = struct{}{} 101 return true 102 } 103 } 104 } 105 return false 106 } 107 108 // Contains 是否存在元素 109 func (set *SyncSet) Contains(item VType) bool { 110 var ok bool 111 set.mu.RLock() 112 if set.data != nil { 113 _, ok = set.data[item] 114 } 115 set.mu.RUnlock() 116 return ok 117 } 118 119 // Remove 移除指定元素 120 func (set *SyncSet) Remove(item VType) { 121 set.mu.Lock() 122 if set.data != nil { 123 delete(set.data, item) 124 } 125 set.mu.Unlock() 126 } 127 128 // Size 返回长度 129 func (set *SyncSet) Size() int { 130 set.mu.RLock() 131 l := len(set.data) 132 set.mu.RUnlock() 133 return l 134 } 135 136 // Clear 清理元素 137 func (set *SyncSet) Clear() { 138 set.mu.Lock() 139 set.data = make(map[VType]struct{}) 140 set.mu.Unlock() 141 } 142 143 // Slice 返回元素slice 144 func (set *SyncSet) Slice() []VType { 145 set.mu.RLock() 146 var i = 0 147 var ret = make([]VType, len(set.data)) 148 for item := range set.data { 149 ret[i] = item 150 i++ 151 } 152 set.mu.RUnlock() 153 return ret 154 } 155 156 // LockFunc 锁住当前set调用方法f 157 func (set *SyncSet) LockFunc(f func(m map[VType]struct{})) { 158 set.mu.Lock() 159 defer set.mu.Unlock() 160 f(set.data) 161 } 162 163 // RLockFunc 读锁住当前set调用方法f 164 func (set *SyncSet) RLockFunc(f func(m map[VType]struct{})) { 165 set.mu.RLock() 166 defer set.mu.RUnlock() 167 f(set.data) 168 } 169 170 // Equal 是否相等 171 func (set *SyncSet) Equal(other *SyncSet) bool { 172 if set == other { 173 return true 174 } 175 set.mu.RLock() 176 defer set.mu.RUnlock() 177 other.mu.RLock() 178 defer other.mu.RUnlock() 179 if len(set.data) != len(other.data) { 180 return false 181 } 182 for key := range set.data { 183 if _, ok := other.data[key]; !ok { 184 return false 185 } 186 } 187 return true 188 } 189 190 // Merge 合并set,返回当前set 191 func (set *SyncSet) Merge(others ...*SyncSet) *SyncSet { 192 set.mu.Lock() 193 defer set.mu.Unlock() 194 for _, other := range others { 195 if set != other { 196 other.mu.RLock() 197 } 198 for k, v := range other.data { 199 set.data[k] = v 200 } 201 if set != other { 202 other.mu.RUnlock() 203 } 204 } 205 return set 206 } 207 208 // Walk 对每个元素作用f方法 209 func (set *SyncSet) Walk(f func(item VType) VType) *SyncSet { 210 set.mu.Lock() 211 defer set.mu.Unlock() 212 m := make(map[VType]struct{}, len(set.data)) 213 for k, v := range set.data { 214 m[f(k)] = v 215 } 216 set.data = m 217 return set 218 } 219 220 type localRWMutexVType struct { 221 *sync.RWMutex 222 } 223 224 func newLocalRWMutexVType(safe bool) *localRWMutexVType { 225 mu := localRWMutexVType{} 226 if safe { 227 mu.RWMutex = new(sync.RWMutex) 228 } 229 return &mu 230 } 231 232 func (mu *localRWMutexVType) IsSafe() bool { 233 return mu.RWMutex != nil 234 } 235 236 func (mu *localRWMutexVType) Lock() { 237 if mu.RWMutex != nil { 238 mu.RWMutex.Lock() 239 } 240 } 241 242 func (mu *localRWMutexVType) Unlock() { 243 if mu.RWMutex != nil { 244 mu.RWMutex.Unlock() 245 } 246 } 247 248 func (mu *localRWMutexVType) RLock() { 249 if mu.RWMutex != nil { 250 mu.RWMutex.RLock() 251 } 252 } 253 254 func (mu *localRWMutexVType) RUnlock() { 255 if mu.RWMutex != nil { 256 mu.RWMutex.RUnlock() 257 } 258 }