-
Notifications
You must be signed in to change notification settings - Fork 1
/
job.go
153 lines (139 loc) · 3.16 KB
/
job.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
package job
import (
"github.com/axe/axe-go/pkg/ds"
)
/*
Example Jobs:
- Get user input
- Read & apply network packets
- Build & write network packet
- Update physics
- Update navigation mesh
- Update path finding
- Update steering behaviors
- Update state machines
- Update space
- Update audio
- Update particles
- Update animations
- Update interface
- Voxel: update lighting
- Voxel: build chunk mesh
- Load & process assets
- Run scripts
- Compute render state
- Render frame
- Display frame
- Recalibrate Jobs (turn on profiling, update costs & budget)
*/
type JobLogic interface {
Run(job *Job)
IsActive() bool
IsAlive() bool
}
type JobDependency struct {
Dependency *Job
Dependent *Job
Required bool
}
type Job struct {
// The unique ID of this job
ID int
// The name of this job
Name string
// The group of this job which dictates ordering
Group uint8
// The cost of this job
Cost int
// If this job should be executed asynchronously
Async bool
// If this job should only be executed after a job with this ID is
After int
// If the job should stricly follow the wait times. So if the wait time is 20 then the job will try to run 50 times a second exactly.
Strict bool
// The minimum milliseconds we should wait between execution
MinWait int64
// The maximum milliseconds we should wait between execution
MaxWait int64
// The last computed wait time
WaitTime int64
// The last time this job ran
LastRun int64
// The last duration between the last run and the previous run
LastDuration int64
// If the job should be profiled
Profile bool
// The last profile start in nanos
ProfileStart int64
// The last profile end in nanos
ProfileEnd int64
// The logic which executes the job
Logic JobLogic
}
var _ ds.Sortable[*Job] = &Job{}
var nextJobID = 0
func New(defaults Job) *Job {
job := defaults
if job.ID == 0 {
job.ID = nextJobID
nextJobID++
}
return &job
}
func (job *Job) Run(time int64, profile bool) {
jobProfile := profile || job.Profile
if jobProfile {
job.ProfileStart = currentNanos()
}
job.Logic.Run(job)
if jobProfile {
job.ProfileEnd = currentNanos()
}
if job.Strict && job.MinWait > 0 {
job.LastDuration = job.MinWait
job.LastRun += job.MinWait
} else {
job.LastDuration = time - job.LastRun
job.LastRun = time
}
}
func (job *Job) SetFrequency(frequency int64) {
job.Strict = true
job.MinWait = frequency
job.MaxWait = frequency
}
func (job *Job) GetWaitTime(time int64, planned map[int]bool) int64 {
if job.After != 0 && !planned[job.After] {
return -1
}
since := time - job.LastRun
if since < job.MinWait {
return -1
}
if job.MaxWait > 0 && since > job.MaxWait {
return 0
}
if job.MinWait > 0 {
return since - job.MinWait
}
if job.MaxWait > 0 {
return since - job.MaxWait
}
return 1
}
func (job *Job) UpdateWaitTime(time int64, planned map[int]bool) {
job.WaitTime = job.GetWaitTime(time, planned)
}
func (job *Job) Less(other *Job) bool {
return job.WaitTime < other.WaitTime
}
func (job *Job) IsBehind(time int64) bool {
since := time - job.LastRun
if job.Strict && job.MinWait > 0 && since > job.MinWait {
return true
}
if job.MaxWait > 0 && since > job.MaxWait {
return true
}
return false
}