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