Skip to content

Commit 8562e08

Browse files
committed
rename
1 parent 8a70cc5 commit 8562e08

File tree

4 files changed

+107
-76
lines changed

4 files changed

+107
-76
lines changed

map.go

+12-74
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,37 @@
11
package lrc
22

3-
import (
4-
"runtime"
5-
"sync/atomic"
6-
)
7-
8-
const ReadOnLeft int32 = -1
9-
const ReadOnRight int32 = 1
10-
113
type LRMap struct {
12-
readIndicators [2]*readIndicator
13-
versionIndex *int32
14-
sideToRead *int32
4+
*LeftRight
155

166
left map[int]int
177
right map[int]int
188
}
199

20-
func New() *LRMap {
10+
func newIntMap() *LRMap {
2111

2212
m := &LRMap{
23-
readIndicators: [2]*readIndicator{
24-
newReadIndicator(),
25-
newReadIndicator(),
26-
},
27-
versionIndex: new(int32),
28-
sideToRead: new(int32),
29-
3013
left: make(map[int]int),
3114
right: make(map[int]int),
3215
}
3316

34-
*m.versionIndex = 0
35-
*m.sideToRead = ReadOnLeft
36-
return m
37-
}
38-
39-
func (lr *LRMap) arrive() int {
40-
idx := atomic.LoadInt32(lr.versionIndex)
41-
lr.readIndicators[idx].arrive()
42-
return int(idx)
43-
}
44-
45-
func (lr *LRMap) depart(localVI int) {
46-
lr.readIndicators[localVI].depart()
47-
}
48-
49-
func (lr *LRMap) toggleVersionAndWait() {
50-
51-
localVI := atomic.LoadInt32(lr.versionIndex)
52-
prevVI := int(localVI % 2)
53-
nextVI := int((localVI + 1) % 2)
54-
55-
for !lr.readIndicators[nextVI].isEmpty() {
56-
runtime.Gosched()
57-
}
58-
59-
atomic.StoreInt32(lr.versionIndex, int32(nextVI))
17+
m.LeftRight = New()
6018

61-
for !lr.readIndicators[prevVI].isEmpty() {
62-
runtime.Gosched()
63-
}
19+
return m
6420
}
6521

6622
func (lr *LRMap) Get(k int) (val int, exist bool) {
6723

68-
lvi := lr.arrive()
69-
70-
which := atomic.LoadInt32(lr.sideToRead)
71-
if which == ReadOnLeft {
72-
val, exist = lr.left[k]
73-
} else {
74-
val, exist = lr.right[k]
75-
}
24+
lr.ApplyReadFn(lr.left, lr.right, func(instance interface{}) {
25+
m := instance.(map[int]int)
26+
val, exist = m[k]
27+
})
7628

77-
lr.depart(lvi)
7829
return
7930
}
8031

8132
func (lr *LRMap) Put(key, val int) {
82-
83-
side := atomic.LoadInt32(lr.sideToRead)
84-
if side == ReadOnLeft {
85-
// write on right
86-
lr.right[key] = val
87-
atomic.StoreInt32(lr.sideToRead, ReadOnRight)
88-
lr.toggleVersionAndWait()
89-
lr.left[key] = val
90-
} else if side == ReadOnRight {
91-
// write on left
92-
lr.left[key] = val
93-
atomic.StoreInt32(lr.sideToRead, ReadOnLeft)
94-
lr.toggleVersionAndWait()
95-
lr.right[key] = val
96-
} else {
97-
panic("illegal state: you can only read on LEFT or RIGHT")
98-
}
33+
lr.ApplyWriteFn(lr.left, lr.right, func(instance interface{}) {
34+
m := instance.(map[int]int)
35+
m[key] = val
36+
})
9937
}

map_bench_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func InitLockMap(num int) *LockMap {
4545
}
4646

4747
func InitLRMap(num int) *LRMap {
48-
lrmap := New()
48+
lrmap := newIntMap()
4949

5050
for i := 0; i < num; i++ {
5151
lrmap.Put(i, i)

map_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
)
88

99
func TestLRMap(t *testing.T) {
10-
lrmap := New()
10+
lrmap := newIntMap()
1111

1212
wg := sync.WaitGroup{}
1313

primitive.go

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package lrc
2+
3+
import (
4+
"runtime"
5+
"sync/atomic"
6+
)
7+
8+
const ReadOnLeft int32 = -1
9+
const ReadOnRight int32 = 1
10+
11+
type LeftRight struct {
12+
readIndicators [2]*readIndicator
13+
versionIndex *int32
14+
sideToRead *int32
15+
}
16+
17+
func New() *LeftRight {
18+
19+
m := &LeftRight{
20+
readIndicators: [2]*readIndicator{
21+
newReadIndicator(),
22+
newReadIndicator(),
23+
},
24+
versionIndex: new(int32),
25+
sideToRead: new(int32),
26+
}
27+
28+
*m.versionIndex = 0
29+
*m.sideToRead = ReadOnLeft
30+
return m
31+
}
32+
33+
func (lr *LeftRight) arrive() int {
34+
idx := atomic.LoadInt32(lr.versionIndex)
35+
lr.readIndicators[idx].arrive()
36+
return int(idx)
37+
}
38+
39+
func (lr *LeftRight) depart(localVI int) {
40+
lr.readIndicators[localVI].depart()
41+
}
42+
43+
func (lr *LeftRight) toggleVersionAndWait() {
44+
45+
localVI := atomic.LoadInt32(lr.versionIndex)
46+
prevVI := int(localVI % 2)
47+
nextVI := int((localVI + 1) % 2)
48+
49+
for !lr.readIndicators[nextVI].isEmpty() {
50+
runtime.Gosched()
51+
}
52+
53+
atomic.StoreInt32(lr.versionIndex, int32(nextVI))
54+
55+
for !lr.readIndicators[prevVI].isEmpty() {
56+
runtime.Gosched()
57+
}
58+
}
59+
60+
func (lr *LeftRight) ApplyReadFn(l interface{}, r interface{}, fn func(interface{})) {
61+
62+
lvi := lr.arrive()
63+
64+
which := atomic.LoadInt32(lr.sideToRead)
65+
if which == ReadOnLeft {
66+
fn(l)
67+
} else {
68+
fn(r)
69+
}
70+
71+
lr.depart(lvi)
72+
return
73+
}
74+
75+
func (lr *LRMap) ApplyWriteFn(l interface{}, r interface{}, fn func(interface{})) {
76+
77+
side := atomic.LoadInt32(lr.sideToRead)
78+
if side == ReadOnLeft {
79+
// write on right
80+
fn(r)
81+
atomic.StoreInt32(lr.sideToRead, ReadOnRight)
82+
lr.toggleVersionAndWait()
83+
fn(l)
84+
} else if side == ReadOnRight {
85+
// write on left
86+
fn(l)
87+
atomic.StoreInt32(lr.sideToRead, ReadOnLeft)
88+
lr.toggleVersionAndWait()
89+
fn(r)
90+
} else {
91+
panic("illegal state: you can only read on LEFT or RIGHT")
92+
}
93+
}

0 commit comments

Comments
 (0)