drivers/timers: map deadlines to facets
This commit is contained in:
parent
e0b569e465
commit
2aaa588f6a
|
@ -1,9 +1,9 @@
|
||||||
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
||||||
# SPDX-License-Identifier: Unlicense
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
import std/times
|
import std/[tables, times]
|
||||||
import preserves
|
import preserves
|
||||||
import ../../syndicate, ../bags, ../protocols/[timer, dataspace]
|
import ../../syndicate, ../protocols/[timer, dataspace]
|
||||||
|
|
||||||
when defined(solo5):
|
when defined(solo5):
|
||||||
import solo5_dispatcher
|
import solo5_dispatcher
|
||||||
|
@ -27,7 +27,7 @@ when defined(solo5):
|
||||||
## Owning facet of driver.
|
## Owning facet of driver.
|
||||||
target: Cap
|
target: Cap
|
||||||
## Destination for LaterThan assertions.
|
## Destination for LaterThan assertions.
|
||||||
deadlines: Bag[float]
|
deadlines: Table[float, Facet]
|
||||||
## Deadlines that other actors are observing.
|
## Deadlines that other actors are observing.
|
||||||
|
|
||||||
proc spawnTimerDriver(facet: Facet; cap: Cap): TimerDriver =
|
proc spawnTimerDriver(facet: Facet; cap: Cap): TimerDriver =
|
||||||
|
@ -35,11 +35,12 @@ when defined(solo5):
|
||||||
|
|
||||||
proc await(driver: TimerDriver; deadline: float) {.solo5dispatch.} =
|
proc await(driver: TimerDriver; deadline: float) {.solo5dispatch.} =
|
||||||
yieldUntil(deadline)
|
yieldUntil(deadline)
|
||||||
if deadline in driver.deadlines:
|
let facet = driver.deadlines.getOrDefault(deadline)
|
||||||
|
if not facet.isNil:
|
||||||
# check if the deadline is still observed
|
# check if the deadline is still observed
|
||||||
proc turnWork(turn: var Turn) =
|
proc turnWork(turn: var Turn) =
|
||||||
discard publish(turn, driver.target, LaterThan(seconds: deadline))
|
discard publish(turn, driver.target, LaterThan(seconds: deadline))
|
||||||
run(driver.facet, turnWork)
|
run(facet, turnWork)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import std/[oserrors, posix, sets]
|
import std/[oserrors, posix, sets]
|
||||||
|
@ -84,7 +85,7 @@ else:
|
||||||
## Owning facet of driver.
|
## Owning facet of driver.
|
||||||
target: Cap
|
target: Cap
|
||||||
## Destination for LaterThan assertions.
|
## Destination for LaterThan assertions.
|
||||||
deadlines: Bag[float]
|
deadlines: Table[float, Facet]
|
||||||
## Deadlines that other actors are observing.
|
## Deadlines that other actors are observing.
|
||||||
timers: HashSet[cint]
|
timers: HashSet[cint]
|
||||||
# TODO: use a single timer descriptor
|
# TODO: use a single timer descriptor
|
||||||
|
@ -100,7 +101,7 @@ else:
|
||||||
proc earliestFloat(driver: TimerDriver): float =
|
proc earliestFloat(driver: TimerDriver): float =
|
||||||
assert driver.deadlines.len > 0
|
assert driver.deadlines.len > 0
|
||||||
result = high float
|
result = high float
|
||||||
for deadline in driver.deadlines:
|
for deadline in driver.deadlines.keys:
|
||||||
if deadline < result:
|
if deadline < result:
|
||||||
result = deadline
|
result = deadline
|
||||||
|
|
||||||
|
@ -119,11 +120,12 @@ else:
|
||||||
# Check if the timer is expired which
|
# Check if the timer is expired which
|
||||||
# could happen before waiting.
|
# could happen before waiting.
|
||||||
wait(FD fd, Read)
|
wait(FD fd, Read)
|
||||||
if deadline in driver.deadlines:
|
let facet = driver.deadlines.getOrDefault(deadline)
|
||||||
|
if not facet.isNil:
|
||||||
# Check if the deadline is still observed.
|
# Check if the deadline is still observed.
|
||||||
proc turnWork(turn: var Turn) =
|
proc turnWork(turn: var Turn) =
|
||||||
discard publish(turn, driver.target, LaterThan(seconds: deadline))
|
discard publish(turn, driver.target, LaterThan(seconds: deadline))
|
||||||
run(driver.facet, turnWork)
|
run(facet, turnWork)
|
||||||
discard close(fd)
|
discard close(fd)
|
||||||
driver.timers.excl(fd)
|
driver.timers.excl(fd)
|
||||||
|
|
||||||
|
@ -134,11 +136,10 @@ proc spawnTimerDriver*(turn: var Turn; ds: Cap): Actor {.discardable.} =
|
||||||
let driver = spawnTimerDriver(turn.facet, ds)
|
let driver = spawnTimerDriver(turn.facet, ds)
|
||||||
let pat = inject(grab Observe(pattern: dropType LaterThan), {0: grabLit()})
|
let pat = inject(grab Observe(pattern: dropType LaterThan), {0: grabLit()})
|
||||||
during(turn, ds, pat) do (deadline: float):
|
during(turn, ds, pat) do (deadline: float):
|
||||||
if change(driver.deadlines, deadline, +1) == cdAbsentToPresent:
|
driver.deadlines[deadline] = turn.facet
|
||||||
discard trampoline(whelp await(driver, deadline))
|
discard trampoline(whelp await(driver, deadline))
|
||||||
do:
|
do:
|
||||||
discard change(driver.deadlines, deadline, -1, clamp = true)
|
driver.deadlines.del deadline
|
||||||
# TODO: retract assertions that are unobserved.
|
|
||||||
|
|
||||||
proc after*(turn: var Turn; ds: Cap; dur: Duration; act: TurnAction) =
|
proc after*(turn: var Turn; ds: Cap; dur: Duration; act: TurnAction) =
|
||||||
## Execute `act` after some duration of time.
|
## Execute `act` after some duration of time.
|
||||||
|
|
Loading…
Reference in New Issue