github.com/sandwich-go/boost@v1.3.29/xcontainer/smap/gen_int64_string.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 DefaultShardCountInt64String = uint64(32) 20 21 type Int64String struct { 22 shardedList []*shardedInt64String 23 shardedCount uint64 24 } 25 26 type shardedInt64String struct { 27 items map[int64]string 28 sync.RWMutex 29 } 30 31 type TupleInt64String struct { 32 Key int64 33 Val string 34 } 35 36 // NewWithSharedCount 返回协程安全版本 37 func NewWithSharedCountInt64String(sharedCount uint64) *Int64String { 38 p := &Int64String{ 39 shardedCount: sharedCount, 40 shardedList: make([]*shardedInt64String, sharedCount), 41 } 42 for i := uint64(0); i < sharedCount; i++ { 43 p.shardedList[i] = &shardedInt64String{items: make(map[int64]string)} 44 } 45 return p 46 } 47 48 // New 返回协程安全版本 49 func NewInt64String() *Int64String { 50 return NewWithSharedCountInt64String(DefaultShardCountInt64String) 51 } 52 53 // GetShard 返回key对应的分片 54 func (m *Int64String) GetShard(key int64) *shardedInt64String { 55 return m.shardedList[KeyToHashInt64(key)%m.shardedCount] 56 } 57 58 // IsEmpty 返回容器是否为空 59 func (m *Int64String) IsEmpty() bool { 60 return m.Count() == 0 61 } 62 63 // Set 设定元素 64 func (m *Int64String) Set(key int64, value string) { 65 shard := m.GetShard(key) 66 shard.Lock() 67 shard.items[key] = value 68 shard.Unlock() 69 } 70 71 // Keys 返回所有的key列表 72 func (m *Int64String) Keys() []int64 { 73 var ret []int64 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 *Int64String) GetAll() map[int64]string { 86 data := make(map[int64]string) 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 *Int64String) Clear() { 99 for _, shard := range m.shardedList { 100 shard.Lock() 101 shard.items = make(map[int64]string) 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 *Int64String) ClearWithFuncLock(onClear func(key int64, val string)) { 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[int64]string) 121 shard.Unlock() 122 } 123 } 124 125 // MGet 返回多个元素 126 func (m *Int64String) MGet(keys ...int64) map[int64]string { 127 data := make(map[int64]string) 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 *Int64String) MSet(data map[int64]string) { 138 for key, value := range data { 139 m.Set(key, value) 140 } 141 } 142 143 // SetNX 如果key不存在,则设定为value, 设定成功则返回true,否则返回false 144 func (m *Int64String) SetNX(key int64, value string) (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 *Int64String) LockFuncWithKey(key int64, f func(shardData map[int64]string)) { 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 *Int64String) RLockFuncWithKey(key int64, f func(shardData map[int64]string)) { 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 *Int64String) LockFunc(f func(shardData map[int64]string)) { 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 *Int64String) RLockFunc(f func(shardData map[int64]string)) { 210 for _, shard := range m.shardedList { 211 shard.RLock() 212 f(shard.items) 213 shard.RUnlock() 214 } 215 } 216 217 func (m *Int64String) doSetWithLockCheck(key int64, val string) (result string, 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 *Int64String) doSetWithLockCheckWithFunc(key int64, f func(key int64) string) (result string, 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 *Int64String) GetOrSetFunc(key int64, f func(key int64) string) (result string, 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 *Int64String) GetOrSetFuncLock(key int64, f func(key int64) string) (result string, 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 *Int64String) GetOrSet(key int64, val string) (string, 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 *Int64String) Get(key int64) (string, 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 *Int64String) Len() int { return m.Count() } 292 293 // Size Count方法别名 294 func (m *Int64String) Size() int { return m.Count() } 295 296 // Count 返回容器内元素数量 297 func (m *Int64String) 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 *Int64String) Has(key int64) 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 *Int64String) Remove(key int64) { 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 *Int64String) GetAndRemove(key int64) (string, 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 *Int64String) Iter() <-chan TupleInt64String { 344 ch := make(chan TupleInt64String) 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 <- TupleInt64String{key, val} 352 } 353 shard.RUnlock() 354 } 355 close(ch) 356 }() 357 return ch 358 } 359 360 // IterBuffered 迭代当前容器内所有元素,使用有缓冲chan,缓冲区大小等于容器大小,迭代过程中操作容器是安全的 361 func (m *Int64String) IterBuffered() <-chan TupleInt64String { 362 ch := make(chan TupleInt64String, 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 <- TupleInt64String{key, val} 370 } 371 shard.RUnlock() 372 } 373 close(ch) 374 }() 375 return ch 376 } 377 378 //template format 379 var __formatKTypeToInt64String = func(i interface{}) int64 { 380 switch ii := i.(type) { 381 case int: 382 return int64(ii) 383 case int8: 384 return int64(ii) 385 case int16: 386 return int64(ii) 387 case int32: 388 return int64(ii) 389 case int64: 390 return int64(ii) 391 case uint: 392 return int64(ii) 393 case uint8: 394 return int64(ii) 395 case uint16: 396 return int64(ii) 397 case uint32: 398 return int64(ii) 399 case uint64: 400 return int64(ii) 401 case float32: 402 return int64(ii) 403 case float64: 404 return int64(ii) 405 case string: 406 iv, err := strconv.ParseInt(ii, 10, 64) 407 if err != nil { 408 panic(err) 409 } 410 return int64(iv) 411 default: 412 panic("unknown type") 413 } 414 } 415 416 //template format 417 var __formatVTypeToInt64String = func(i interface{}) string { 418 switch ii := i.(type) { 419 case string: 420 return ii 421 default: 422 return fmt.Sprintf("%d", i) 423 } 424 }