github.com/sandwich-go/boost@v1.3.29/xcontainer/smap/gen_int_int.go (about) 1 // Code generated by gotemplate. DO NOT EDIT. 2 3 // smap 包提供了一个分片的协程安全的映射 4 // NewWithSharedCount 返回一个线程安全的映射实例 5 // New 返回一个线程安全的映射实例 6 package smap 7 8 import ( 9 "strconv" 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 DefaultShardCountIntInt = uint64(32) 19 20 type IntInt struct { 21 shardedList []*shardedIntInt 22 shardedCount uint64 23 } 24 25 type shardedIntInt struct { 26 items map[int]int 27 sync.RWMutex 28 } 29 30 type TupleIntInt struct { 31 Key int 32 Val int 33 } 34 35 // NewWithSharedCount 返回协程安全版本 36 func NewWithSharedCountIntInt(sharedCount uint64) *IntInt { 37 p := &IntInt{ 38 shardedCount: sharedCount, 39 shardedList: make([]*shardedIntInt, sharedCount), 40 } 41 for i := uint64(0); i < sharedCount; i++ { 42 p.shardedList[i] = &shardedIntInt{items: make(map[int]int)} 43 } 44 return p 45 } 46 47 // New 返回协程安全版本 48 func NewIntInt() *IntInt { 49 return NewWithSharedCountIntInt(DefaultShardCountIntInt) 50 } 51 52 // GetShard 返回key对应的分片 53 func (m *IntInt) GetShard(key int) *shardedIntInt { 54 return m.shardedList[KeyToHashInt(key)%m.shardedCount] 55 } 56 57 // IsEmpty 返回容器是否为空 58 func (m *IntInt) IsEmpty() bool { 59 return m.Count() == 0 60 } 61 62 // Set 设定元素 63 func (m *IntInt) Set(key int, value int) { 64 shard := m.GetShard(key) 65 shard.Lock() 66 shard.items[key] = value 67 shard.Unlock() 68 } 69 70 // Keys 返回所有的key列表 71 func (m *IntInt) Keys() []int { 72 var ret []int 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 *IntInt) GetAll() map[int]int { 85 data := make(map[int]int) 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 *IntInt) Clear() { 98 for _, shard := range m.shardedList { 99 shard.Lock() 100 shard.items = make(map[int]int) 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 *IntInt) ClearWithFuncLock(onClear func(key int, val int)) { 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[int]int) 120 shard.Unlock() 121 } 122 } 123 124 // MGet 返回多个元素 125 func (m *IntInt) MGet(keys ...int) map[int]int { 126 data := make(map[int]int) 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 *IntInt) MSet(data map[int]int) { 137 for key, value := range data { 138 m.Set(key, value) 139 } 140 } 141 142 // SetNX 如果key不存在,则设定为value, 设定成功则返回true,否则返回false 143 func (m *IntInt) SetNX(key int, value int) (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 *IntInt) LockFuncWithKey(key int, f func(shardData map[int]int)) { 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 *IntInt) RLockFuncWithKey(key int, f func(shardData map[int]int)) { 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 *IntInt) LockFunc(f func(shardData map[int]int)) { 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 *IntInt) RLockFunc(f func(shardData map[int]int)) { 209 for _, shard := range m.shardedList { 210 shard.RLock() 211 f(shard.items) 212 shard.RUnlock() 213 } 214 } 215 216 func (m *IntInt) doSetWithLockCheck(key int, val int) (result int, 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 *IntInt) doSetWithLockCheckWithFunc(key int, f func(key int) int) (result int, 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 *IntInt) GetOrSetFunc(key int, f func(key int) int) (result int, 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 *IntInt) GetOrSetFuncLock(key int, f func(key int) int) (result int, 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 *IntInt) GetOrSet(key int, val int) (int, 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 *IntInt) Get(key int) (int, 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 *IntInt) Len() int { return m.Count() } 291 292 // Size Count方法别名 293 func (m *IntInt) Size() int { return m.Count() } 294 295 // Count 返回容器内元素数量 296 func (m *IntInt) 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 *IntInt) Has(key int) 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 *IntInt) Remove(key int) { 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 *IntInt) GetAndRemove(key int) (int, 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 *IntInt) Iter() <-chan TupleIntInt { 343 ch := make(chan TupleIntInt) 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 <- TupleIntInt{key, val} 351 } 352 shard.RUnlock() 353 } 354 close(ch) 355 }() 356 return ch 357 } 358 359 // IterBuffered 迭代当前容器内所有元素,使用有缓冲chan,缓冲区大小等于容器大小,迭代过程中操作容器是安全的 360 func (m *IntInt) IterBuffered() <-chan TupleIntInt { 361 ch := make(chan TupleIntInt, 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 <- TupleIntInt{key, val} 369 } 370 shard.RUnlock() 371 } 372 close(ch) 373 }() 374 return ch 375 } 376 377 //template format 378 var __formatKTypeToIntInt = func(i interface{}) int { 379 switch ii := i.(type) { 380 case int: 381 return int(ii) 382 case int8: 383 return int(ii) 384 case int16: 385 return int(ii) 386 case int32: 387 return int(ii) 388 case int64: 389 return int(ii) 390 case uint: 391 return int(ii) 392 case uint8: 393 return int(ii) 394 case uint16: 395 return int(ii) 396 case uint32: 397 return int(ii) 398 case uint64: 399 return int(ii) 400 case float32: 401 return int(ii) 402 case float64: 403 return int(ii) 404 case string: 405 iv, err := strconv.ParseInt(ii, 10, 64) 406 if err != nil { 407 panic(err) 408 } 409 return int(iv) 410 default: 411 panic("unknown type") 412 } 413 } 414 415 //template format 416 var __formatVTypeToIntInt = func(i interface{}) int { 417 switch ii := i.(type) { 418 case int: 419 return int(ii) 420 case int8: 421 return int(ii) 422 case int16: 423 return int(ii) 424 case int32: 425 return int(ii) 426 case int64: 427 return int(ii) 428 case uint: 429 return int(ii) 430 case uint8: 431 return int(ii) 432 case uint16: 433 return int(ii) 434 case uint32: 435 return int(ii) 436 case uint64: 437 return int(ii) 438 case float32: 439 return int(ii) 440 case float64: 441 return int(ii) 442 case string: 443 iv, err := strconv.ParseInt(ii, 10, 64) 444 if err != nil { 445 panic(err) 446 } 447 return int(iv) 448 default: 449 panic("unknown type") 450 } 451 }