github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/easy/ezmap/safe.go (about)

     1  package ezmap
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"time"
     7  
     8  	"gopkg.in/yaml.v3"
     9  )
    10  
    11  // SafeMap wraps a Map with a RWMutex to provide concurrent safety.
    12  // It's safe for concurrent use by multiple goroutines.
    13  type SafeMap struct {
    14  	mu   sync.RWMutex
    15  	map_ Map //nolint:revive
    16  }
    17  
    18  // NewSafeMap returns a new initialized SafeMap.
    19  func NewSafeMap() *SafeMap {
    20  	return &SafeMap{map_: make(Map)}
    21  }
    22  
    23  // MarshalJSON implements the json.Marshaler interface.
    24  func (p *SafeMap) MarshalJSON() ([]byte, error) {
    25  	p.mu.RLock()
    26  	defer p.mu.RUnlock()
    27  	return p.map_.MarshalJSON()
    28  }
    29  
    30  // MarshalJSONPretty returns its marshaled data as `[]byte` with
    31  // indentation using two spaces.
    32  func (p *SafeMap) MarshalJSONPretty() ([]byte, error) {
    33  	p.mu.RLock()
    34  	defer p.mu.RUnlock()
    35  	return p.map_.MarshalJSONPretty()
    36  }
    37  
    38  // UnmarshalJSON implements the json.Unmarshaler interface.
    39  func (p *SafeMap) UnmarshalJSON(data []byte) error {
    40  	p.mu.Lock()
    41  	defer p.mu.Unlock()
    42  	return p.map_.UnmarshalJSON(data)
    43  }
    44  
    45  // MarshalYAML implements the [yaml.Marshaler] interface.
    46  func (p *SafeMap) MarshalYAML() (any, error) {
    47  	p.mu.RLock()
    48  	defer p.mu.RUnlock()
    49  	return p.map_.MarshalYAML()
    50  }
    51  
    52  // UnmarshalYAML implements the [yaml.Unmarshaler] interface.
    53  func (p *SafeMap) UnmarshalYAML(value *yaml.Node) error {
    54  	p.mu.Lock()
    55  	defer p.mu.Unlock()
    56  	return p.map_.UnmarshalYAML(value)
    57  }
    58  
    59  // Size returns the number of elements in the map.
    60  func (p *SafeMap) Size() int {
    61  	p.mu.RLock()
    62  	defer p.mu.RUnlock()
    63  	return len(p.map_)
    64  }
    65  
    66  // Set is used to store a new key/value pair exclusively in the map.
    67  // It also lazily initializes the map if it was not used previously.
    68  func (p *SafeMap) Set(key string, value any) {
    69  	p.mu.Lock()
    70  	p.map_.Set(key, value)
    71  	p.mu.Unlock()
    72  }
    73  
    74  // Get returns the value for the given key, ie: (value, true).
    75  // If the value does not exist it returns (nil, false)
    76  func (p *SafeMap) Get(key string) (value any, exists bool) {
    77  	p.mu.RLock()
    78  	value, exists = p.map_.Get(key)
    79  	p.mu.RUnlock()
    80  	return
    81  }
    82  
    83  // GetOr returns the value for the given key if it exists in the map,
    84  // else it returns the default value.
    85  func (p *SafeMap) GetOr(key string, defaultVal any) (value any) {
    86  	p.mu.RLock()
    87  	value = p.map_.GetOr(key, defaultVal)
    88  	p.mu.RUnlock()
    89  	return
    90  }
    91  
    92  // MustGet returns the value for the given key if it exists, otherwise it panics.
    93  func (p *SafeMap) MustGet(key string) any {
    94  	var (
    95  		value  any
    96  		exists bool
    97  	)
    98  	p.mu.RLock()
    99  	value, exists = p.map_.Get(key)
   100  	p.mu.RLock()
   101  	if exists {
   102  		return value
   103  	}
   104  	panic(fmt.Sprintf("key %q not exists", key))
   105  }
   106  
   107  // GetString returns the value associated with the key as a string.
   108  func (p *SafeMap) GetString(key string) string {
   109  	return getWithRLock(&p.mu, p.map_.GetString, key)
   110  }
   111  
   112  // GetBytes returns the value associated with the key as bytes.
   113  func (p *SafeMap) GetBytes(key string) []byte {
   114  	return getWithRLock(&p.mu, p.map_.GetBytes, key)
   115  }
   116  
   117  // GetBool returns the value associated with the key as a boolean value.
   118  func (p *SafeMap) GetBool(key string) bool {
   119  	return getWithRLock(&p.mu, p.map_.GetBool, key)
   120  }
   121  
   122  // GetInt returns the value associated with the key as an int.
   123  func (p *SafeMap) GetInt(key string) int {
   124  	return getWithRLock(&p.mu, p.map_.GetInt, key)
   125  }
   126  
   127  // GetInt32 returns the value associated with the key as an int32.
   128  func (p *SafeMap) GetInt32(key string) int32 {
   129  	return getWithRLock(&p.mu, p.map_.GetInt32, key)
   130  }
   131  
   132  // GetInt64 returns the value associated with the key as an int64.
   133  func (p *SafeMap) GetInt64(key string) int64 {
   134  	return getWithRLock(&p.mu, p.map_.GetInt64, key)
   135  }
   136  
   137  // GetUint returns the value associated with the key as an uint.
   138  func (p *SafeMap) GetUint(key string) uint {
   139  	return getWithRLock(&p.mu, p.map_.GetUint, key)
   140  }
   141  
   142  // GetUint32 returns the value associated with the key as an uint32.
   143  func (p *SafeMap) GetUint32(key string) uint32 {
   144  	return getWithRLock(&p.mu, p.map_.GetUint32, key)
   145  }
   146  
   147  // GetUint64 returns the value associated with the key as an uint64.
   148  func (p *SafeMap) GetUint64(key string) uint64 {
   149  	return getWithRLock(&p.mu, p.map_.GetUint64, key)
   150  }
   151  
   152  // GetFloat returns the value associated with the key as a float64.
   153  func (p *SafeMap) GetFloat(key string) float64 {
   154  	return getWithRLock(&p.mu, p.map_.GetFloat, key)
   155  }
   156  
   157  // GetTime returns the value associated with the key as time.
   158  func (p *SafeMap) GetTime(key string) time.Time {
   159  	return getWithRLock(&p.mu, p.map_.GetTime, key)
   160  }
   161  
   162  // GetDuration returns the value associated with the key as a duration.
   163  func (p *SafeMap) GetDuration(key string) time.Duration {
   164  	return getWithRLock(&p.mu, p.map_.GetDuration, key)
   165  }
   166  
   167  // GetInt64s returns the value associated with the key as a slice of int64.
   168  func (p *SafeMap) GetInt64s(key string) []int64 {
   169  	return getWithRLock(&p.mu, p.map_.GetInt64s, key)
   170  }
   171  
   172  // GetInt32s returns the value associated with the key as a slice of int32.
   173  func (p *SafeMap) GetInt32s(key string) []int32 {
   174  	return getWithRLock(&p.mu, p.map_.GetInt32s, key)
   175  }
   176  
   177  // GetStrings returns the value associated with the key as a slice of strings.
   178  func (p *SafeMap) GetStrings(key string) []string {
   179  	return getWithRLock(&p.mu, p.map_.GetStrings, key)
   180  }
   181  
   182  // GetSlice returns the value associated with the key as a slice.
   183  // It returns nil if key does not present in Map or the value's type
   184  // is not a slice.
   185  func (p *SafeMap) GetSlice(key string) any {
   186  	return getWithRLock(&p.mu, p.map_.GetSlice, key)
   187  }
   188  
   189  // GetMap returns the value associated with the key as a Map (map[string]any).
   190  func (p *SafeMap) GetMap(key string) Map {
   191  	return getWithRLock(&p.mu, p.map_.GetMap, key)
   192  }
   193  
   194  // GetStringMap returns the value associated with the key as a map of (map[string]string).
   195  func (p *SafeMap) GetStringMap(key string) map[string]string {
   196  	return getWithRLock(&p.mu, p.map_.GetStringMap, key)
   197  }
   198  
   199  // Iterate iterates the map in unspecified order, the given function fn
   200  // will be called for each key value pair.
   201  // The iteration can be aborted by returning a non-zero value from fn.
   202  func (p *SafeMap) Iterate(fn func(k string, v any) int) {
   203  	p.mu.RLock()
   204  	defer p.mu.RUnlock()
   205  	p.map_.Iterate(fn)
   206  }
   207  
   208  // Merge merges key values from another map.
   209  func (p *SafeMap) Merge(other map[string]any) {
   210  	p.mu.Lock()
   211  	defer p.mu.Unlock()
   212  	p.map_.Merge(other)
   213  }
   214  
   215  func getWithRLock[T any](mu *sync.RWMutex, f func(key string) T, key string) (ret T) {
   216  	mu.RLock()
   217  	ret = f(key)
   218  	mu.RUnlock()
   219  	return
   220  }