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