LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value. The loaded result is true if the value was loaded, false if stored.
(key K, value V)
| 209 | // Otherwise, it stores and returns the given value. |
| 210 | // The loaded result is true if the value was loaded, false if stored. |
| 211 | func (m *MapOf[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) { |
| 212 | // Avoid locking if it's a clean hit. |
| 213 | read, _ := m.read.Load().(readOnly[K, V]) |
| 214 | if e, ok := read.m[key]; ok { |
| 215 | actual, loaded, ok := e.tryLoadOrStore(value) |
| 216 | if ok { |
| 217 | return actual, loaded |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | m.mu.Lock() |
| 222 | read, _ = m.read.Load().(readOnly[K, V]) |
| 223 | if e, ok := read.m[key]; ok { |
| 224 | if e.unexpungeLocked() { |
| 225 | m.dirty[key] = e |
| 226 | } |
| 227 | actual, loaded, _ = e.tryLoadOrStore(value) |
| 228 | } else if e, ok := m.dirty[key]; ok { |
| 229 | actual, loaded, _ = e.tryLoadOrStore(value) |
| 230 | m.missLocked() |
| 231 | } else { |
| 232 | if !read.amended { |
| 233 | // We're adding the first new key to the dirty map. |
| 234 | // Make sure it is allocated and mark the read-only map as incomplete. |
| 235 | m.dirtyLocked() |
| 236 | m.read.Store(readOnly[K, V]{m: read.m, amended: true}) |
| 237 | } |
| 238 | m.dirty[key] = newEntry(value) |
| 239 | actual, loaded = value, false |
| 240 | } |
| 241 | m.mu.Unlock() |
| 242 | |
| 243 | return actual, loaded |
| 244 | } |
| 245 | |
| 246 | // tryLoadOrStore atomically loads or stores a value if the entry is not |
| 247 | // expunged. |
no test coverage detected