-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrequest.go
More file actions
95 lines (85 loc) · 2.04 KB
/
Copy pathrequest.go
File metadata and controls
95 lines (85 loc) · 2.04 KB
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
92
93
94
95
package boc
import (
"fmt"
"sync/atomic"
)
var glbReqId atomic.Int64
// request for cown
type request struct {
next atomic.Pointer[behavior] // next behavior to be executed
scheduled atomic.Bool // indicates if the request has been scheduled
target cownBase // target cown the request wants to access
// for debug use
prev_req *request // previous request in the queue
id int64 // request id for debug use
done bool // request has been released
resolveBehavior *behavior // behavior to be resolved
}
// String returns a string representation of the request
func (r *request) String() string {
return fmt.Sprintf("r%d", r.id)
}
func newRequest(target cownBase) *request {
return &request{
prev_req: nil,
next: atomic.Pointer[behavior]{},
scheduled: atomic.Bool{},
target: target,
id: glbReqId.Add(1),
done: false,
}
}
func (r *request) startEnqueue(behavior *behavior) {
prev := r.target.getLast().Swap(r)
if prev != nil {
r.prev_req = prev
first := true
for !prev.scheduled.Load() {
if first {
first = false
if debug {
fmt.Println(r, "waiting", prev, "to be scheduled")
}
}
}
if !first {
if debug {
fmt.Println(r, "waiting succ")
}
}
prev.next.Store(behavior)
return
}
debugRequestResolveBehavior(r, behavior)
behavior.resolveOne()
r.resolveBehavior = behavior
r.done = true
}
func (r *request) finishEnqueue() {
r.scheduled.Store(true)
if debug {
fmt.Println("scheduled", r)
}
}
func (r *request) release() {
if r.next.Load() == nil {
if r.target.getLast().CompareAndSwap(r, nil) {
return
}
for r.next.Load() == nil {
if debug {
fmt.Println(r, "'s next is nil, waiting for it to be set")
}
}
}
b := r.next.Load()
debugRequestResolveBehavior(r, b)
b.resolveOne()
r.resolveBehavior = b
r.done = true
}
func debugRequestResolveBehavior(r *request, b *behavior) {
if debug {
fmt.Println(r, ": --", b, "remaining", b.count.Load()-1, "/total", len(b.requests))
}
}