-
Notifications
You must be signed in to change notification settings - Fork 0
/
pointer_stack.go
91 lines (77 loc) · 1.83 KB
/
pointer_stack.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package adhoctx
import (
"unsafe"
)
type PointerStack struct {
OldVersion *PointerStack
PointersByID []*unsafe.Pointer
LowestFreeSlot uint32
}
func (l *PointerStack) New() *PointerStack {
newPs := &PointerStack{OldVersion: l}
if l != nil {
newPs.PointersByID = make([]*unsafe.Pointer, len(l.PointersByID), len(l.PointersByID))
copy(newPs.PointersByID, l.PointersByID)
}
return newPs
}
func (l *PointerStack) Allocate(n unsafe.Pointer) uint32 {
for i, ptr := range l.PointersByID[l.LowestFreeSlot:] {
if ptr == nil {
l.PointersByID[l.LowestFreeSlot+uint32(i)] = &n
return l.LowestFreeSlot + uint32(i)
}
}
newIDX := uint32(len(l.PointersByID))
l.LowestFreeSlot = newIDX
l.PointersByID = append(l.PointersByID, &n)
return newIDX
}
func (l *PointerStack) Remove(n uint32) {
if l.LowestFreeSlot < n {
l.LowestFreeSlot = n
}
l.PointersByID[n] = nil
}
func (l PointerStack) Get(n uint32) unsafe.Pointer {
if l.PointersByID == nil {
return *l.OldVersion.PointersByID[n]
}
return *l.PointersByID[n]
}
type PointerStackView struct {
atomicCommitter
}
func NewPointerStackView() *PointerStackView {
return new(PointerStackView)
}
func (d *PointerStackView) Current() *PointerStack {
return (*PointerStack)(d.getCurrent('p'))
}
func (d *PointerStackView) Commit(version *PointerStack) bool {
oldVersion := version.OldVersion
version.OldVersion = nil
return d.tryCommit('p', unsafe.Pointer(oldVersion), unsafe.Pointer(version))
}
func (d *PointerStackView) AllocateID(p unsafe.Pointer) uint32 {
for {
t := d.Current().New()
id := t.Allocate(p)
if d.Commit(t) {
return id
}
}
}
func (d *PointerStackView) RemoveID(id uint32) {
for {
t := d.Current().New()
t.Remove(id)
if d.Commit(t) {
return
}
}
}
func (d *PointerStackView) GetPointer(id uint32) unsafe.Pointer {
ptr := d.Current().Get(id)
return ptr
}