github.com/sandwich-go/boost@v1.3.29/xcontainer/templates/sset/sset.go (about)

     1  // sset 包提供了多种类型的集合
     2  // 可以产生一个带读写锁的线程安全的SyncSet,也可以产生一个非线程安全的SyncSet
     3  // New 产生非协程安全的版本
     4  // NewSync 产生协程安全的版本
     5  package sset
     6  
     7  import (
     8  	"sync"
     9  )
    10  
    11  //template type SyncSet(VType)
    12  
    13  type VType interface{}
    14  
    15  // SyncSet 包含一个读写锁和一个map,根据不同需求可提供对切片协程安全版本或者非协程安全版本的实例
    16  type SyncSet struct {
    17  	mu   *localRWMutexVType
    18  	data map[VType]struct{}
    19  }
    20  
    21  // New 创建非协程安全版本
    22  func New() *SyncSet { return newWithSafe(false) }
    23  
    24  // NewSync 创建协程安全版本
    25  func NewSync() *SyncSet { return newWithSafe(true) }
    26  
    27  func newWithSafe(safe bool) *SyncSet {
    28  	return &SyncSet{data: make(map[VType]struct{}), mu: newLocalRWMutexVType(safe)}
    29  }
    30  
    31  // Iterator 遍历
    32  func (set *SyncSet) Iterator(f func(v VType) bool) {
    33  	set.mu.RLock()
    34  	defer set.mu.RUnlock()
    35  	for k := range set.data {
    36  		if !f(k) {
    37  			break
    38  		}
    39  	}
    40  }
    41  
    42  // Add 添加元素
    43  func (set *SyncSet) Add(items ...VType) {
    44  	set.mu.Lock()
    45  	if set.data == nil {
    46  		set.data = make(map[VType]struct{})
    47  	}
    48  	for _, v := range items {
    49  		set.data[v] = struct{}{}
    50  	}
    51  	set.mu.Unlock()
    52  }
    53  
    54  // AddIfNotExist 如果元素不存在则添加,如添加成功则返回true
    55  func (set *SyncSet) AddIfNotExist(item VType) (addOK bool) {
    56  	if !set.Contains(item) {
    57  		set.mu.Lock()
    58  		defer set.mu.Unlock()
    59  		if set.data == nil {
    60  			set.data = make(map[VType]struct{})
    61  		}
    62  		if _, ok := set.data[item]; !ok {
    63  			set.data[item] = struct{}{}
    64  			return true
    65  		}
    66  	}
    67  	return false
    68  }
    69  
    70  // AddIfNotExistFunc 如果元素不存在且f返回true则添加,如添加成功则返回true
    71  // f函数运行在lock之外
    72  func (set *SyncSet) AddIfNotExistFunc(item VType, f func() bool) bool {
    73  	if !set.Contains(item) {
    74  		if f() {
    75  			set.mu.Lock()
    76  			defer set.mu.Unlock()
    77  			if set.data == nil {
    78  				set.data = make(map[VType]struct{})
    79  			}
    80  			if _, ok := set.data[item]; !ok {
    81  				set.data[item] = struct{}{}
    82  				return true
    83  			}
    84  		}
    85  	}
    86  	return false
    87  }
    88  
    89  // AddIfNotExistFuncLock 如果元素不存在且f返回true则添加,如添加成功则返回true
    90  // f函数运行在lock之内
    91  func (set *SyncSet) AddIfNotExistFuncLock(item VType, f func() bool) bool {
    92  	if !set.Contains(item) {
    93  		set.mu.Lock()
    94  		defer set.mu.Unlock()
    95  		if set.data == nil {
    96  			set.data = make(map[VType]struct{})
    97  		}
    98  		if f() {
    99  			if _, ok := set.data[item]; !ok {
   100  				set.data[item] = struct{}{}
   101  				return true
   102  			}
   103  		}
   104  	}
   105  	return false
   106  }
   107  
   108  // Contains 是否存在元素
   109  func (set *SyncSet) Contains(item VType) bool {
   110  	var ok bool
   111  	set.mu.RLock()
   112  	if set.data != nil {
   113  		_, ok = set.data[item]
   114  	}
   115  	set.mu.RUnlock()
   116  	return ok
   117  }
   118  
   119  // Remove 移除指定元素
   120  func (set *SyncSet) Remove(item VType) {
   121  	set.mu.Lock()
   122  	if set.data != nil {
   123  		delete(set.data, item)
   124  	}
   125  	set.mu.Unlock()
   126  }
   127  
   128  // Size 返回长度
   129  func (set *SyncSet) Size() int {
   130  	set.mu.RLock()
   131  	l := len(set.data)
   132  	set.mu.RUnlock()
   133  	return l
   134  }
   135  
   136  // Clear 清理元素
   137  func (set *SyncSet) Clear() {
   138  	set.mu.Lock()
   139  	set.data = make(map[VType]struct{})
   140  	set.mu.Unlock()
   141  }
   142  
   143  // Slice 返回元素slice
   144  func (set *SyncSet) Slice() []VType {
   145  	set.mu.RLock()
   146  	var i = 0
   147  	var ret = make([]VType, len(set.data))
   148  	for item := range set.data {
   149  		ret[i] = item
   150  		i++
   151  	}
   152  	set.mu.RUnlock()
   153  	return ret
   154  }
   155  
   156  // LockFunc 锁住当前set调用方法f
   157  func (set *SyncSet) LockFunc(f func(m map[VType]struct{})) {
   158  	set.mu.Lock()
   159  	defer set.mu.Unlock()
   160  	f(set.data)
   161  }
   162  
   163  // RLockFunc 读锁住当前set调用方法f
   164  func (set *SyncSet) RLockFunc(f func(m map[VType]struct{})) {
   165  	set.mu.RLock()
   166  	defer set.mu.RUnlock()
   167  	f(set.data)
   168  }
   169  
   170  // Equal 是否相等
   171  func (set *SyncSet) Equal(other *SyncSet) bool {
   172  	if set == other {
   173  		return true
   174  	}
   175  	set.mu.RLock()
   176  	defer set.mu.RUnlock()
   177  	other.mu.RLock()
   178  	defer other.mu.RUnlock()
   179  	if len(set.data) != len(other.data) {
   180  		return false
   181  	}
   182  	for key := range set.data {
   183  		if _, ok := other.data[key]; !ok {
   184  			return false
   185  		}
   186  	}
   187  	return true
   188  }
   189  
   190  // Merge 合并set,返回当前set
   191  func (set *SyncSet) Merge(others ...*SyncSet) *SyncSet {
   192  	set.mu.Lock()
   193  	defer set.mu.Unlock()
   194  	for _, other := range others {
   195  		if set != other {
   196  			other.mu.RLock()
   197  		}
   198  		for k, v := range other.data {
   199  			set.data[k] = v
   200  		}
   201  		if set != other {
   202  			other.mu.RUnlock()
   203  		}
   204  	}
   205  	return set
   206  }
   207  
   208  // Walk 对每个元素作用f方法
   209  func (set *SyncSet) Walk(f func(item VType) VType) *SyncSet {
   210  	set.mu.Lock()
   211  	defer set.mu.Unlock()
   212  	m := make(map[VType]struct{}, len(set.data))
   213  	for k, v := range set.data {
   214  		m[f(k)] = v
   215  	}
   216  	set.data = m
   217  	return set
   218  }
   219  
   220  type localRWMutexVType struct {
   221  	*sync.RWMutex
   222  }
   223  
   224  func newLocalRWMutexVType(safe bool) *localRWMutexVType {
   225  	mu := localRWMutexVType{}
   226  	if safe {
   227  		mu.RWMutex = new(sync.RWMutex)
   228  	}
   229  	return &mu
   230  }
   231  
   232  func (mu *localRWMutexVType) IsSafe() bool {
   233  	return mu.RWMutex != nil
   234  }
   235  
   236  func (mu *localRWMutexVType) Lock() {
   237  	if mu.RWMutex != nil {
   238  		mu.RWMutex.Lock()
   239  	}
   240  }
   241  
   242  func (mu *localRWMutexVType) Unlock() {
   243  	if mu.RWMutex != nil {
   244  		mu.RWMutex.Unlock()
   245  	}
   246  }
   247  
   248  func (mu *localRWMutexVType) RLock() {
   249  	if mu.RWMutex != nil {
   250  		mu.RWMutex.RLock()
   251  	}
   252  }
   253  
   254  func (mu *localRWMutexVType) RUnlock() {
   255  	if mu.RWMutex != nil {
   256  		mu.RWMutex.RUnlock()
   257  	}
   258  }