-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdependency.go
156 lines (141 loc) · 3.16 KB
/
dependency.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package gotcc
import (
"sort"
)
// A dependency expression is a filter to describe the tasks' dependency
// A task will be launched only if the expression is true.
type DependencyExpression struct {
f func() bool
allAnd bool
}
func MakeNotExpr(Expr DependencyExpression) DependencyExpression {
return DependencyExpression{
f: func() bool {
return !Expr.f()
},
allAnd: false,
}
}
func MakeAndExpr(Expr1 DependencyExpression, Expr2 DependencyExpression) DependencyExpression {
return DependencyExpression{
f: func() bool {
return Expr1.f() && Expr2.f()
},
allAnd: Expr1.allAnd && Expr2.allAnd,
}
}
func MakeOrExpr(Expr1 DependencyExpression, Expr2 DependencyExpression) DependencyExpression {
return DependencyExpression{
f: func() bool {
return Expr1.f() || Expr2.f()
},
allAnd: false,
}
}
func MakeXorExpr(Expr1 DependencyExpression, Expr2 DependencyExpression) DependencyExpression {
return DependencyExpression{
f: func() bool {
return (Expr1.f() && !Expr2.f()) || (!Expr1.f() && Expr2.f())
},
allAnd: false,
}
}
func newDependencyExpr(valMap map[uint32]bool, key uint32) DependencyExpression {
return DependencyExpression{
f: func() bool {
return valMap[key]
},
allAnd: true,
}
}
func (m *TCController) analyzeDependency() (map[uint32]int, bool) {
const (
white = 0
gray = 1
black = 2
)
color := map[uint32]int{}
order := map[uint32]int{}
var dfs func(curr uint32) bool
dfs = func(curr uint32) bool {
if len(m.executors[curr].dependency) == 0 {
order[curr] = 0
color[curr] = black
return true
}
color[curr] = gray
maxorder := 0
for neighbor := range m.executors[curr].dependency {
switch color[neighbor] {
case white:
if !dfs(neighbor) {
return false
}
maxorder = max(maxorder, order[neighbor])
case gray:
return false
case black:
maxorder = max(maxorder, order[neighbor])
}
}
color[curr] = black
order[curr] = maxorder + 1
return true
}
for taskid := range m.executors {
if !dfs(taskid) {
return nil, false
}
}
return order, true
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
func (m *TCController) sortExecutor(taskorder map[uint32]int) ([]uint32, bool) {
type item struct {
taskid uint32
taskname string
order int
}
itemlist := make([]item, 0, len(taskorder))
res := make([]uint32, 0, len(taskorder))
for taskid, order := range taskorder {
e := m.executors[taskid]
if !e.dependencyExpr.allAnd {
return nil, false
}
itemlist = append(itemlist, item{
taskid: taskid,
taskname: e.name,
order: order,
})
}
sort.Slice(itemlist, func(i, j int) bool {
if itemlist[i].order == itemlist[j].order {
return itemlist[i].taskname < itemlist[j].taskname
}
return itemlist[i].order < itemlist[j].order
})
for i := range itemlist {
res = append(res, itemlist[i].taskid)
}
return res, true
}
// default dependency expression: always return true
var DefaultTrueExpr = DependencyExpression{
f: func() bool {
return true
},
allAnd: true,
}
// default dependency expression: always return false
var DefaultFalseExpr = DependencyExpression{
f: func() bool {
return false
},
allAnd: true,
}