github.com/sandwich-go/boost@v1.3.29/xcontainer/smap/gen_string_any.go (about) 1 // Code generated by gotemplate. DO NOT EDIT. 2 3 // smap 包提供了一个分片的协程安全的映射 4 // NewWithSharedCount 返回一个线程安全的映射实例 5 // New 返回一个线程安全的映射实例 6 package smap 7 8 import ( 9 "fmt" 10 "sync" 11 ) 12 13 //template type Concurrent(KType,VType,KeyHash) 14 15 // A thread safe map. 16 // To avoid lock bottlenecks this map is dived to several (DefaultShardCount) map shards. 17 18 var DefaultShardCountStringAny = uint64(32) 19 20 type StringAny struct { 21 shardedList []*shardedStringAny 22 shardedCount uint64 23 } 24 25 type shardedStringAny struct { 26 items map[string]interface{} 27 sync.RWMutex 28 } 29 30 type TupleStringAny struct { 31 Key string 32 Val interface{} 33 } 34 35 // NewWithSharedCount 返回协程安全版本 36 func NewWithSharedCountStringAny(sharedCount uint64) *StringAny { 37 p := &StringAny{ 38 shardedCount: sharedCount, 39 shardedList: make([]*shardedStringAny, sharedCount), 40 } 41 for i := uint64(0); i < sharedCount; i++ { 42 p.shardedList[i] = &shardedStringAny{items: make(map[string]interface{})} 43 } 44 return p 45 } 46 47 // New 返回协程安全版本 48 func NewStringAny() *StringAny { 49 return NewWithSharedCountStringAny(DefaultShardCountStringAny) 50 } 51 52 // GetShard 返回key对应的分片 53 func (m *StringAny) GetShard(key string) *shardedStringAny { 54 return m.shardedList[KeyToHashString(key)%m.shardedCount] 55 } 56 57 // IsEmpty 返回容器是否为空 58 func (m *StringAny) IsEmpty() bool { 59 return m.Count() == 0 60 } 61 62 // Set 设定元素 63 func (m *StringAny) Set(key string, value interface{}) { 64 shard := m.GetShard(key) 65 shard.Lock() 66 shard.items[key] = value 67 shard.Unlock() 68 } 69 70 // Keys 返回所有的key列表 71 func (m *StringAny) Keys() []string { 72 var ret []string 73 for _, shard := range m.shardedList { 74 shard.RLock() 75 for key := range shard.items { 76 ret = append(ret, key) 77 } 78 shard.RUnlock() 79 } 80 return ret 81 } 82 83 // GetAll 返回所有元素副本,其中value浅拷贝 84 func (m *StringAny) GetAll() map[string]interface{} { 85 data := make(map[string]interface{}) 86 for _, shard := range m.shardedList { 87 shard.RLock() 88 for key, val := range shard.items { 89 data[key] = val 90 } 91 shard.RUnlock() 92 } 93 return data 94 } 95 96 // Clear 清空元素 97 func (m *StringAny) Clear() { 98 for _, shard := range m.shardedList { 99 shard.Lock() 100 shard.items = make(map[string]interface{}) 101 shard.Unlock() 102 } 103 } 104 105 // ClearWithFunc 清空元素,onClear在对应分片的Lock内执行,执行完毕后对容器做整体clear操作 106 // 107 // Note: 不要在onClear对当前容器做读写操作,容易死锁 108 // 109 // data.ClearWithFuncLock(func(key string,val string) { 110 // data.Get(...) // 死锁 111 // }) 112 // 113 func (m *StringAny) ClearWithFuncLock(onClear func(key string, val interface{})) { 114 for _, shard := range m.shardedList { 115 shard.Lock() 116 for key, val := range shard.items { 117 onClear(key, val) 118 } 119 shard.items = make(map[string]interface{}) 120 shard.Unlock() 121 } 122 } 123 124 // MGet 返回多个元素 125 func (m *StringAny) MGet(keys ...string) map[string]interface{} { 126 data := make(map[string]interface{}) 127 for _, key := range keys { 128 if val, ok := m.Get(key); ok { 129 data[key] = val 130 } 131 } 132 return data 133 } 134 135 // MSet 同时设定多个元素 136 func (m *StringAny) MSet(data map[string]interface{}) { 137 for key, value := range data { 138 m.Set(key, value) 139 } 140 } 141 142 // SetNX 如果key不存在,则设定为value, 设定成功则返回true,否则返回false 143 func (m *StringAny) SetNX(key string, value interface{}) (isSet bool) { 144 shard := m.GetShard(key) 145 shard.Lock() 146 if _, ok := shard.items[key]; !ok { 147 shard.items[key] = value 148 isSet = true 149 } 150 shard.Unlock() 151 return isSet 152 } 153 154 // LockFuncWithKey 对key对应的分片加写锁,并用f操作该分片内数据 155 // 156 // Note: 不要对f中对容器的该分片做读写操作,可以直接操作shardData数据源 157 // 158 // data.LockFuncWithKey("test",func(shardData map[string]string) { 159 // data.Remove("test") // 当前分片已被加读锁, 死锁 160 // }) 161 // 162 func (m *StringAny) LockFuncWithKey(key string, f func(shardData map[string]interface{})) { 163 shard := m.GetShard(key) 164 shard.Lock() 165 defer shard.Unlock() 166 f(shard.items) 167 } 168 169 // RLockFuncWithKey 对key对应的分片加读锁,并用f操作该分片内数据 170 // 171 // Note: 不要在f内对容器做写操作,否则会引起死锁,可以直接操作shardData数据源 172 // 173 // data.RLockFuncWithKey("test",func(shardData map[string]string) { 174 // data.Remove("test") // 当前分片已被加读锁, 死锁 175 // }) 176 // 177 func (m *StringAny) RLockFuncWithKey(key string, f func(shardData map[string]interface{})) { 178 shard := m.GetShard(key) 179 shard.RLock() 180 defer shard.RUnlock() 181 f(shard.items) 182 } 183 184 // LockFunc 遍历容器分片,f在Lock写锁内执行 185 // 186 // Note: 不要在f内对容器做读写操作,否则会引起死锁,可以直接操作shardData数据源 187 // 188 // data.LockFunc(func(shardData map[string]string) { 189 // data.Count() // 当前分片已被加写锁, 死锁 190 // }) 191 // 192 func (m *StringAny) LockFunc(f func(shardData map[string]interface{})) { 193 for _, shard := range m.shardedList { 194 shard.Lock() 195 f(shard.items) 196 shard.Unlock() 197 } 198 } 199 200 // RLockFunc 遍历容器分片,f在RLock读锁内执行 201 // 202 // Note: 不要在f内对容器做修改操作,否则会引起死锁,可以直接操作shardData数据源 203 // 204 // data.RLockFunc(func(shardData map[string]string) { 205 // data.Remove("test") // 当前分片已被加读锁, 死锁 206 // }) 207 // 208 func (m *StringAny) RLockFunc(f func(shardData map[string]interface{})) { 209 for _, shard := range m.shardedList { 210 shard.RLock() 211 f(shard.items) 212 shard.RUnlock() 213 } 214 } 215 216 func (m *StringAny) doSetWithLockCheck(key string, val interface{}) (result interface{}, isSet bool) { 217 shard := m.GetShard(key) 218 shard.Lock() 219 220 if got, ok := shard.items[key]; ok { 221 shard.Unlock() 222 return got, false 223 } 224 225 shard.items[key] = val 226 isSet = true 227 result = val 228 shard.Unlock() 229 return 230 } 231 232 func (m *StringAny) doSetWithLockCheckWithFunc(key string, f func(key string) interface{}) (result interface{}, isSet bool) { 233 shard := m.GetShard(key) 234 shard.Lock() 235 236 if got, ok := shard.items[key]; ok { 237 shard.Unlock() 238 return got, false 239 } 240 241 val := f(key) 242 shard.items[key] = val 243 isSet = true 244 result = val 245 shard.Unlock() 246 return 247 } 248 249 // GetOrSetFunc 获取或者设定数值,方法f在Lock写锁外执行, 如元素早已存在则返回false,设定成功返回true 250 func (m *StringAny) GetOrSetFunc(key string, f func(key string) interface{}) (result interface{}, isSet bool) { 251 if v, ok := m.Get(key); ok { 252 return v, false 253 } 254 return m.doSetWithLockCheck(key, f(key)) 255 } 256 257 // GetOrSetFuncLock 获取或者设定数值,方法f在Lock写锁内执行, 如元素早已存在则返回false,设定成功返回true 258 // 259 // Note: 不要在f内对容器做操作,否则会死锁 260 // 261 // data.GetOrSetFuncLock(“test”,func(key string)string { 262 // data.Count() // 死锁 263 // }) 264 // 265 func (m *StringAny) GetOrSetFuncLock(key string, f func(key string) interface{}) (result interface{}, isSet bool) { 266 if v, ok := m.Get(key); ok { 267 return v, false 268 } 269 return m.doSetWithLockCheckWithFunc(key, f) 270 } 271 272 // GetOrSet 获取或设定元素, 如元素早已存在则返回false,设定成功返回true 273 func (m *StringAny) GetOrSet(key string, val interface{}) (interface{}, bool) { 274 if v, ok := m.Get(key); ok { 275 return v, false 276 } 277 return m.doSetWithLockCheck(key, val) 278 } 279 280 // Get 返回key对应的元素,不存在返回false 281 func (m *StringAny) Get(key string) (interface{}, bool) { 282 shard := m.GetShard(key) 283 shard.RLock() 284 val, ok := shard.items[key] 285 shard.RUnlock() 286 return val, ok 287 } 288 289 // Len Count方法别名 290 func (m *StringAny) Len() int { return m.Count() } 291 292 // Size Count方法别名 293 func (m *StringAny) Size() int { return m.Count() } 294 295 // Count 返回容器内元素数量 296 func (m *StringAny) Count() int { 297 count := 0 298 for i := uint64(0); i < m.shardedCount; i++ { 299 shard := m.shardedList[i] 300 shard.RLock() 301 count += len(shard.items) 302 shard.RUnlock() 303 } 304 return count 305 } 306 307 // Has 是否存在key对应的元素 308 func (m *StringAny) Has(key string) bool { 309 shard := m.GetShard(key) 310 shard.RLock() 311 _, ok := shard.items[key] 312 shard.RUnlock() 313 return ok 314 } 315 316 // Remove 删除key对应的元素 317 func (m *StringAny) Remove(key string) { 318 shard := m.GetShard(key) 319 shard.Lock() 320 delete(shard.items, key) 321 shard.Unlock() 322 } 323 324 // GetAndRemove 返回key对应的元素并将其由容器中删除,如果元素不存在则返回false 325 func (m *StringAny) GetAndRemove(key string) (interface{}, bool) { 326 shard := m.GetShard(key) 327 shard.Lock() 328 val, ok := shard.items[key] 329 delete(shard.items, key) 330 shard.Unlock() 331 return val, ok 332 } 333 334 // Iter 迭代当前容器内所有元素,使用无缓冲chan 335 // 336 // Note: 不要在迭代过程中对当前容器作修改操作(申请写锁),容易会产生死锁 337 // 338 // for v:= data.Iter() { 339 // data.Remove(v.Key) // 尝试删除元素申请分片Lock,但是Iter内部的迭代协程对分片做了RLock,导致死锁 340 // } 341 // 342 func (m *StringAny) Iter() <-chan TupleStringAny { 343 ch := make(chan TupleStringAny) 344 go func() { 345 // Foreach shard. 346 for _, shard := range m.shardedList { 347 shard.RLock() 348 // Foreach key, value pair. 349 for key, val := range shard.items { 350 ch <- TupleStringAny{key, val} 351 } 352 shard.RUnlock() 353 } 354 close(ch) 355 }() 356 return ch 357 } 358 359 // IterBuffered 迭代当前容器内所有元素,使用有缓冲chan,缓冲区大小等于容器大小,迭代过程中操作容器是安全的 360 func (m *StringAny) IterBuffered() <-chan TupleStringAny { 361 ch := make(chan TupleStringAny, m.Count()) 362 go func() { 363 // Foreach shard. 364 for _, shard := range m.shardedList { 365 // Foreach key, value pair. 366 shard.RLock() 367 for key, val := range shard.items { 368 ch <- TupleStringAny{key, val} 369 } 370 shard.RUnlock() 371 } 372 close(ch) 373 }() 374 return ch 375 } 376 377 //template format 378 var __formatKTypeToStringAny = func(i interface{}) string { 379 switch ii := i.(type) { 380 case string: 381 return ii 382 default: 383 return fmt.Sprintf("%d", i) 384 } 385 } 386 387 //template format 388 var __formatVTypeToStringAny = func(i interface{}) interface{} { 389 return i 390 }