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