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 }