53 lines
1.6 KiB
Nim
53 lines
1.6 KiB
Nim
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
|
# SPDX-License-Identifier: Unlicense
|
|
|
|
import std/[asyncdispatch, monotimes, times, posix, times, epoll]
|
|
import preserves
|
|
import syndicate
|
|
|
|
import ../protocols/timer
|
|
from ../syndicate/protocols/dataspace import Observe
|
|
|
|
export timer
|
|
|
|
type Observe = dataspace.Observe
|
|
|
|
#[
|
|
proc timerfd_create(clock_id: ClockId, flags: cint): cint
|
|
{.importc: "timerfd_create", header: "<sys/timerfd.h>".}
|
|
proc timerfd_settime(ufd: cint, flags: cint,
|
|
utmr: var Itimerspec, otmr: var Itimerspec): cint
|
|
{.importc: "timerfd_settime", header: "<sys/timerfd.h>".}
|
|
proc eventfd(count: cuint, flags: cint): cint
|
|
{.importc: "eventfd", header: "<sys/eventfd.h>".}
|
|
]#
|
|
|
|
proc now: float64 = getTime().toUnixFloat()
|
|
|
|
proc processTimers(ds: Cap) {.turnAction.} =
|
|
let pat = inject(grab Observe(pattern: dropType LaterThan), {0: grabLit()})
|
|
during(ds, pat) do (seconds: float):
|
|
let period = seconds - now()
|
|
if period < 0.001 or true:
|
|
let h = publish(ds, LaterThan(seconds: seconds).toPreserves)
|
|
|
|
#[
|
|
else:
|
|
let fdi = timerfd_create(CLOCK_MONOTONIC, O_CLOEXEC or O_NONBLOCK)
|
|
|
|
addCallback(sleepAsync(period * 1_000), turn) do (turn: Turn):
|
|
discard publish(turn, ds, LaterThan(seconds: seconds))
|
|
]#
|
|
|
|
proc spawnTimers*(ds: Cap) =
|
|
## Spawn a timer actor.
|
|
boot(newActor("timers"), whelp processTimers(ds))
|
|
|
|
proc after*(turn: Turn; ds: Cap; dur: Duration; act: TurnAction) =
|
|
## Execute `act` after some duration of time.
|
|
let later = now() + dur.inMilliseconds.float64 * 1_000.0
|
|
onPublish(ds, grab LaterThan(seconds: later)):
|
|
act(turn)
|
|
|
|
# TODO: periodic timer
|