Skip to content

Commit 3008455

Browse files
committed
use go1.19 atomic.Pointer
1 parent d7ea0ae commit 3008455

File tree

4 files changed

+20
-91
lines changed

4 files changed

+20
-91
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module github.com/RomiChan/syncx
22

3-
go 1.18
3+
go 1.19

map.go

+19-12
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type Map[K comparable, V any] struct {
4141
// Entries stored in read may be updated concurrently without mu, but updating
4242
// a previously-expunged entry requires that the entry be copied to the dirty
4343
// map and unexpunged with mu held.
44-
read Pointer[readOnly[K]]
44+
read atomic.Pointer[readOnly[K]]
4545

4646
// dirty contains the portion of the map's contents that require mu to be
4747
// held. To ensure that the dirty map can be promoted to the read map quickly,
@@ -102,18 +102,25 @@ func newEntry[V any](i V) *entry {
102102
return &entry{p: unsafe.Pointer(&i)}
103103
}
104104

105+
func (m *Map[K, V]) loadReadOnly() readOnly[K] {
106+
if p := m.read.Load(); p != nil {
107+
return *p
108+
}
109+
return readOnly[K]{}
110+
}
111+
105112
// Load returns the value stored in the map for a key, or nil if no
106113
// value is present.
107114
// The ok result indicates whether value was found in the map.
108115
func (m *Map[K, V]) Load(key K) (value V, ok bool) {
109-
read, _ := m.read.LoadValue()
116+
read := m.loadReadOnly()
110117
e, ok := read.m[key]
111118
if !ok && read.amended {
112119
m.mu.Lock()
113120
// Avoid reporting a spurious miss if m.dirty got promoted while we were
114121
// blocked on m.mu. (If further loads of the same key will not miss, it's
115122
// not worth copying the dirty map for this key.)
116-
read, _ = m.read.LoadValue()
123+
read = m.loadReadOnly()
117124
e, ok = read.m[key]
118125
if !ok && read.amended {
119126
e, ok = m.dirty[key]
@@ -140,13 +147,13 @@ func entryLoad[V any](e *entry) (value V, ok bool) {
140147

141148
// Store sets the value for a key.
142149
func (m *Map[K, V]) Store(key K, value V) {
143-
read, _ := m.read.LoadValue()
150+
read := m.loadReadOnly()
144151
if e, ok := read.m[key]; ok && tryStore(e, &value) {
145152
return
146153
}
147154

148155
m.mu.Lock()
149-
read, _ = m.read.LoadValue()
156+
read = m.loadReadOnly()
150157
if e, ok := read.m[key]; ok {
151158
if e.unexpungeLocked() {
152159
// The entry was previously expunged, which implies that there is a
@@ -204,7 +211,7 @@ func entryStoreLocked[V any](e *entry, i *V) {
204211
// The loaded result is true if the value was loaded, false if stored.
205212
func (m *Map[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
206213
// Avoid locking if it's a clean hit.
207-
read, _ := m.read.LoadValue()
214+
read := m.loadReadOnly()
208215
if e, ok := read.m[key]; ok {
209216
actual, loaded, ok := entryTryLoadOrStore(e, value)
210217
if ok {
@@ -213,7 +220,7 @@ func (m *Map[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
213220
}
214221

215222
m.mu.Lock()
216-
read, _ = m.read.LoadValue()
223+
read = m.loadReadOnly()
217224
if e, ok := read.m[key]; ok {
218225
if e.unexpungeLocked() {
219226
m.dirty[key] = e
@@ -272,11 +279,11 @@ func entryTryLoadOrStore[V any](e *entry, i V) (actual V, loaded, ok bool) {
272279
// LoadAndDelete deletes the value for a key, returning the previous value if any.
273280
// The loaded result reports whether the key was present.
274281
func (m *Map[K, V]) LoadAndDelete(key K) (value V, loaded bool) {
275-
read, _ := m.read.LoadValue()
282+
read := m.loadReadOnly()
276283
e, ok := read.m[key]
277284
if !ok && read.amended {
278285
m.mu.Lock()
279-
read, _ = m.read.LoadValue()
286+
read = m.loadReadOnly()
280287
e, ok = read.m[key]
281288
if !ok && read.amended {
282289
e, ok = m.dirty[key]
@@ -327,14 +334,14 @@ func (m *Map[K, V]) Range(f func(key K, value V) bool) {
327334
// present at the start of the call to Range.
328335
// If read.amended is false, then read.m satisfies that property without
329336
// requiring us to hold m.mu for a long time.
330-
read, _ := m.read.LoadValue()
337+
read := m.loadReadOnly()
331338
if read.amended {
332339
// m.dirty contains keys not in read.m. Fortunately, Range is already O(N)
333340
// (assuming the caller does not break out early), so a call to Range
334341
// amortizes an entire copy of the map: we can promote the dirty copy
335342
// immediately!
336343
m.mu.Lock()
337-
read, _ = m.read.LoadValue()
344+
read = m.loadReadOnly()
338345
if read.amended {
339346
read = readOnly[K]{m: m.dirty}
340347
m.read.Store(&read)
@@ -370,7 +377,7 @@ func (m *Map[K, V]) dirtyLocked() {
370377
return
371378
}
372379

373-
read, _ := m.read.LoadValue()
380+
read := m.loadReadOnly()
374381
m.dirty = make(map[K]*entry, len(read.m))
375382
for k, e := range read.m {
376383
if !e.tryExpungeLocked() {

pointer.go

-54
This file was deleted.

pointer_test.go

-24
This file was deleted.

0 commit comments

Comments
 (0)