-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTime.kt
74 lines (63 loc) · 2.12 KB
/
Time.kt
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
package cf.wayzer.simkt
import kotlinx.coroutines.cancel
import kotlinx.coroutines.runBlocking
import java.util.*
import java.util.concurrent.atomic.AtomicReference
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
@Suppress("unused", "MemberVisibilityCanBePrivate")
object Time {
private val time = AtomicReference(0.0) //seconds
val now get() = time.get()!!
val nowH get() = now.seconds
fun reset() {
queue.forEach { it.cancel() }
queue.clear()
time.set(0.0)
}
private val queue = PriorityQueue<Process>()
fun schedule(process: Process) {
synchronized(queue) {
queue.add(process)
}
}
fun deSchedule(process: Process) = synchronized(queue) {
queue.remove(process)
}
fun run(seconds: Double) {
runBlocking(Process.tracedDispatcher.raw) {
val end = (now + seconds).coerceAtMost(Double.MAX_VALUE)
while (true) {
Process.tracedDispatcher.waitRunning()
if ((queue.peek()?.nextTime ?: Double.POSITIVE_INFINITY) > end) break
synchronized(queue) { queue.poll() }?.let { next ->
time.set(next.nextTime)
next.resume()
}
parallelStrategy.onTick()
}
time.set(end)
}
}
fun run(time: Duration) = run(time.toDouble(DurationUnit.SECONDS))
var parallelStrategy = ParallelStrategy.NoParallel
sealed interface ParallelStrategy {
fun onTick()
object NoParallel : ParallelStrategy {
override fun onTick() = Unit
}
/**
* Allow parallel if the interval less than [eps]
* @param eps max interval to parallel
* */
@Suppress("MemberVisibilityCanBePrivate", "unused")
class WithTimeWrong(val eps: Double) : ParallelStrategy {
override fun onTick() {
while ((queue.peek()?.nextTime ?: Double.MAX_VALUE) < now + eps) {
queue.poll().resume()
}
}
}
}
}