@@ 1,1 1,186 @@
-{"depends":[{"method":"fetchzip","packages":["hashlib"],"path":"/nix/store/v03nzlpdgbfxd2zhcnkfbkq01d5kqxcl-source","rev":"84e0247555e4488594975900401baaf5bbbfb531","sha256":"1pfczsv8kl36qpv543f93d2y2vgz2acckssfap7l51s2x62m6qwx","srcDir":"","url":"https://github.com/khchen/hashlib/archive/84e0247555e4488594975900401baaf5bbbfb531.tar.gz"},{"method":"fetchzip","packages":["nimcrypto"],"path":"/nix/store/zyr8zwh7vaiycn1s4r8cxwc71f2k5l0h-source","ref":"traditional-api","rev":"602c5d20c69c76137201b5d41f788f72afb95aa8","sha256":"1dmdmgb6b9m5f8dyxk781nnd61dsk3hdxqks7idk9ncnpj9fng65","srcDir":"","url":"https://github.com/cheatfate/nimcrypto/archive/602c5d20c69c76137201b5d41f788f72afb95aa8.tar.gz"},{"method":"fetchzip","packages":["npeg"],"path":"/nix/store/ffkxmjmigfs7zhhiiqm0iw2c34smyciy-source","ref":"1.2.1","rev":"26d62fdc40feb84c6533956dc11d5ee9ea9b6c09","sha256":"0xpzifjkfp49w76qmaylan8q181bs45anmp46l4bwr3lkrr7bpwh","srcDir":"src","url":"https://github.com/zevv/npeg/archive/26d62fdc40feb84c6533956dc11d5ee9ea9b6c09.tar.gz"},{"method":"fetchzip","packages":["preserves"],"path":"/nix/store/nrcpzf9hx70kry3gwhrdzcs3qicjncjh-source","ref":"20231021","rev":"edece399be70818208bf2263c30cb2bcf435bbff","sha256":"0xmw35wmw3a4lja9q4qvlvpxv3xk0hnkjg4fwfw6f3inh6zfiqki","srcDir":"src","url":"https://git.syndicate-lang.org/ehmry/preserves-nim/archive/edece399be70818208bf2263c30cb2bcf435bbff.tar.gz"},{"method":"fetchzip","packages":["syndicate"],"path":"/nix/store/1y3nnpp2mhxqmdb3xh4c4k5k5l9hhqk3-source","ref":"20231019","rev":"57b99b20e7db1b97b1cb9c6df574bd13983c26fc","sha256":"1kgb3a78igs37xkmv8cbaxa17qdjf2h43vdmpda517c9086ggsn5","srcDir":"src","url":"https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/57b99b20e7db1b97b1cb9c6df574bd13983c26fc.tar.gz"}]}
+{
+ "depends": [
+ {
+ "method": "fetchzip",
+ "packages": [
+ "bigints"
+ ],
+ "path": "/nix/store/jvrm392g8adfsgf36prgwkbyd7vh5jsw-source",
+ "rev": "86ea14d31eea9275e1408ca34e6bfe9c99989a96",
+ "sha256": "15pcpmnk1bnw3k8769rjzcpg00nahyrypwbxs88jnwr4aczp99j4",
+ "srcDir": "src",
+ "url": "https://github.com/ehmry/nim-bigints/archive/86ea14d31eea9275e1408ca34e6bfe9c99989a96.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "cps"
+ ],
+ "path": "/nix/store/8gbhwni0akqskdb3qhn5nfgv6gkdz0vz-source",
+ "rev": "c90530ac57f98a842b7be969115c6ef08bdcc564",
+ "sha256": "0h8ghs2fqg68j3jdcg7grnxssmllmgg99kym2w0a3vlwca1zvr62",
+ "srcDir": "",
+ "url": "https://github.com/ehmry/cps/archive/c90530ac57f98a842b7be969115c6ef08bdcc564.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "getdns"
+ ],
+ "path": "/nix/store/x9xmn7w4k6jg8nv5bnx148ibhnsfh362-source",
+ "rev": "c73cbe288d9f9480586b8fa87f6d794ffb6a6ce6",
+ "sha256": "1sbgx2x51szr22i72n7c8jglnfmr8m7y7ga0v85d58fwadiv7g6b",
+ "srcDir": "src",
+ "url": "https://git.sr.ht/~ehmry/getdns-nim/archive/c73cbe288d9f9480586b8fa87f6d794ffb6a6ce6.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "getdns"
+ ],
+ "path": "/nix/store/x9xmn7w4k6jg8nv5bnx148ibhnsfh362-source",
+ "rev": "c73cbe288d9f9480586b8fa87f6d794ffb6a6ce6",
+ "sha256": "1sbgx2x51szr22i72n7c8jglnfmr8m7y7ga0v85d58fwadiv7g6b",
+ "srcDir": "src",
+ "url": "https://git.sr.ht/~ehmry/getdns-nim/archive/c73cbe288d9f9480586b8fa87f6d794ffb6a6ce6.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "hashlib"
+ ],
+ "path": "/nix/store/fav82xdbicvlk34nmcbl89zx99lr3mbs-source",
+ "rev": "f9455d4be988e14e3dc7933eb7cc7d7c4820b7ac",
+ "sha256": "1sx6j952lj98629qfgr7ds5aipyw9d6lldcnnqs205wpj4pkcjb3",
+ "srcDir": "",
+ "url": "https://github.com/ehmry/hashlib/archive/f9455d4be988e14e3dc7933eb7cc7d7c4820b7ac.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "nimcrypto"
+ ],
+ "path": "/nix/store/fkrcpp8lzj2yi21na79xm63xk0ggnqsp-source",
+ "rev": "f147d30c69bc1c9bcf0e37f7699bcf0fbaab97b5",
+ "sha256": "1h3dzdbc9kacwpi10mj73yjglvn7kbizj1x8qc9099ax091cj5xn",
+ "srcDir": "",
+ "url": "https://github.com/cheatfate/nimcrypto/archive/f147d30c69bc1c9bcf0e37f7699bcf0fbaab97b5.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "npeg"
+ ],
+ "path": "/nix/store/xpn694ibgipj8xak3j4bky6b3k0vp7hh-source",
+ "rev": "ec0cc6e64ea4c62d2aa382b176a4838474238f8d",
+ "sha256": "1fi9ls3xl20bmv1ikillxywl96i9al6zmmxrbffx448gbrxs86kg",
+ "srcDir": "src",
+ "url": "https://github.com/zevv/npeg/archive/ec0cc6e64ea4c62d2aa382b176a4838474238f8d.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "preserves"
+ ],
+ "path": "/nix/store/2hy124xgabz134dxj3wji7mp47fdwy3w-source",
+ "rev": "9ae435a83c6d5028405538af5d24a023af625b6e",
+ "sha256": "1k7ywcp1a53x2fpc6wc2b0qzb264dkifash0s1wcp66rw3lx15k2",
+ "srcDir": "src",
+ "url": "https://git.syndicate-lang.org/ehmry/preserves-nim/archive/9ae435a83c6d5028405538af5d24a023af625b6e.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "stew"
+ ],
+ "path": "/nix/store/mqg8qzsbcc8xqabq2yzvlhvcyqypk72c-source",
+ "rev": "3c91b8694e15137a81ec7db37c6c58194ec94a6a",
+ "sha256": "17lfhfxp5nxvld78xa83p258y80ks5jb4n53152cdr57xk86y07w",
+ "srcDir": "",
+ "url": "https://github.com/status-im/nim-stew/archive/3c91b8694e15137a81ec7db37c6c58194ec94a6a.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "syndicate"
+ ],
+ "path": "/nix/store/kl628g7vg2ww8wilf8h2ag7qqnvvwdzb-source",
+ "rev": "c2e1e2e0fa403529750196ce3ccb5a99a4d6c006",
+ "sha256": "1r8ab79pgrrnzmp49h8rp50c9x8zd0p7bsvzxaphc221nvyfx09j",
+ "srcDir": "src",
+ "url": "https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/c2e1e2e0fa403529750196ce3ccb5a99a4d6c006.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "sys"
+ ],
+ "path": "/nix/store/syhxsjlsdqfap0hk4qp3s6kayk8cqknd-source",
+ "rev": "4ef3b624db86e331ba334e705c1aa235d55b05e1",
+ "sha256": "1q4qgw4an4mmmcbx48l6xk1jig1vc8p9cq9dbx39kpnb0890j32q",
+ "srcDir": "src",
+ "url": "https://github.com/ehmry/nim-sys/archive/4ef3b624db86e331ba334e705c1aa235d55b05e1.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "sys"
+ ],
+ "path": "/nix/store/vf9ls2wip6d8xhsi3rjh0dqsqg597i6b-source",
+ "rev": "c117ee60542f084525f254e6ade590675a6a2ed6",
+ "sha256": "12qzx2lnh84xqfgypy0pka8nflq0y8n1izfwx8mb4zya5nzawmyf",
+ "srcDir": "src",
+ "url": "https://github.com/alaviss/nim-sys/archive/c117ee60542f084525f254e6ade590675a6a2ed6.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "taps"
+ ],
+ "path": "/nix/store/6y14ia52kr7jyaa0izx37mlablmq9s65-source",
+ "rev": "8c8572cd971d1283e6621006b310993c632da247",
+ "sha256": "1dp166bv9x773jmfqppg5i3v3rilgff013vb11yzwcid9l7s3iy8",
+ "srcDir": "src",
+ "url": "https://git.sr.ht/~ehmry/nim_taps/archive/8c8572cd971d1283e6621006b310993c632da247.tar.gz"
+ },
+ {
+ "date": "2024-04-02T15:38:57+01:00",
+ "deepClone": false,
+ "fetchLFS": false,
+ "fetchSubmodules": true,
+ "hash": "sha256-iZb9aAgYr4FGkqfIg49QWiCqeizIi047kFhugHiP8o0=",
+ "leaveDotGit": false,
+ "method": "git",
+ "packages": [
+ "solo5_dispatcher"
+ ],
+ "path": "/nix/store/sf5dgj2ljvahcm6my7d61ibda51vnrii-solo5_dispatcher",
+ "rev": "a7a894a96a2221284012800e6fd32923d83d20bd",
+ "sha256": "13gjixw80vjqj0xlx2y85ixal82sa27q7j57j9383bqq11lgv5l9",
+ "srcDir": "pkg",
+ "url": "https://git.sr.ht/~ehmry/solo5_dispatcher"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "cps"
+ ],
+ "path": "/nix/store/phdf6siqbhj7vx4qq507lzla81si60iz-source",
+ "rev": "58772ff9ddb38a4b2ec52da142d8532ba2fe7039",
+ "sha256": "1lph7v27nqwgm3a0ssi8q348gjrkjwgqc50agw38j7xif6wj80cw",
+ "srcDir": "",
+ "url": "https://github.com/ehmry/cps/archive/58772ff9ddb38a4b2ec52da142d8532ba2fe7039.tar.gz"
+ },
+ {
+ "method": "fetchzip",
+ "packages": [
+ "stew"
+ ],
+ "path": "/nix/store/mqg8qzsbcc8xqabq2yzvlhvcyqypk72c-source",
+ "rev": "3c91b8694e15137a81ec7db37c6c58194ec94a6a",
+ "sha256": "17lfhfxp5nxvld78xa83p258y80ks5jb4n53152cdr57xk86y07w",
+ "srcDir": "",
+ "url": "https://github.com/status-im/nim-stew/archive/3c91b8694e15137a81ec7db37c6c58194ec94a6a.tar.gz"
+ }
+ ]
+}
@@ 1,12 1,41 @@
-# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway
+# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
-import std/[asyncdispatch, times]
+import std/[oserrors, posix, times]
from std/strutils import toHex
-import preserves, syndicate
-from syndicate/relays import connectStdio
+import pkg/sys/[handles, ioqueue]
+import preserves, syndicate, syndicate/relays
import ./private/solartimes
+type Time = posix.Time
+
+{.pragma: timerfd, importc, header: "<sys/timerfd.h>".}
+
+proc timerfd_create(clock_id: ClockId, flags: cint): cint {.timerfd, used.}
+proc timerfd_settime(ufd: cint, flags: cint,
+ utmr: var Itimerspec, otmr: var Itimerspec): cint {.timerfd, used.}
+proc timerfd_gettime(ufd: cint, curr: var Itimerspec): cint {.timerfd, used.}
+
+var
+ TFD_NONBLOCK {.timerfd.}: cint
+ TFD_CLOEXEC {.timerfd.}: cint
+ TFD_TIMER_ABSTIME {.timerfd.}: cint
+
+proc newHexSecTimer(): cint =
+ var its, old: Itimerspec
+ result = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK or TFD_CLOEXEC)
+ if result < 0:
+ raiseOSError(osLastError(), "failed to acquire timer descriptor")
+ # TODO: Align `its.it_value` to the next hexsec.
+ if clock_gettime(CLOCK_REALTIME, its.it_value) < 0:
+ raiseOSError(osLastError(), "clock_gettime")
+ inc(its.it_value.tv_sec)
+ # inc(its.it_value.tv_nsec, 1_000)
+ its.it_interval.tv_sec = Time 1
+ its.it_interval.tv_nsec = ((24 * 60 * 60 * 1_000_000_000) div 0x1_00_00) mod 1_000_000_000
+ if timerfd_settime(result, TFD_TIMER_ABSTIME, its, old) < 0:
+ raiseOSError(osLastError(), "failed to set timeout")
+
const milisecPerHexsec = (24 * 60 * 60 * 1_000) div 0x1_00_00
type
@@ 14,7 43,6 @@ type
dataspace: Cap
lat: float
lon: float
- interval: float
TonalTime {.preservesRecord: "tonaltime".} = object
num: int64
@@ 28,33 56,43 @@ type
Midnight {.preservesRecord: "midnight".} = object
s: string
-runActor("tonaltime") do (root: Cap; turn: var Turn):
- connectStdio(turn, root)
- during(turn, root, ?Args) do (ds: Cap, interval: float, lat: float, lon: float):
+ Clock = ref object
+ facet: Facet
+ ds: Cap
+ midnight: DateTime
+ timeHandle: syndicate.Handle
+
+proc update(clock: Clock) =
+ run(clock.facet) do (turn: var Turn):
let
- horizon = horizonTimes(lon, lat, now())
- dayDur = horizon.sundown - horizon.sunrise
- noon = horizon.sunrise + (dayDur div 2)
- midnight = noon - initDuration(hours = 12)
-
- discard publish(turn, ds, Sunrise(s: $horizon.sunrise))
- discard publish(turn, ds, Sunset(s: $horizon.sundown))
- discard publish(turn, ds, Noon(s: $noon))
- discard publish(turn, ds, Midnight(s: $midnight))
-
- var timeHandle: Handle
-
- let facet = turn.facet
- proc publishTime {.gcsafe.} =
- facet.run do(turn: var Turn):
- let
- dt = now()
- milisecs = inMilliseconds (dt - midnight)
- hexsecs = milisecs div milisecPerHexsec
- hexStr = toHex(hexsecs shr 12, 1) & "_" & toHex(hexsecs shr 4, 2) & "_" & toHex(hexsecs, 1)
- replace(turn, ds, timeHandle, TonalTime(num: hexsecs, hex: hexStr))
-
- let timeout = int(milisecPerHexsec * interval)
- addTimer(timeout, oneshot = true) do (fd: AsyncFD) -> bool:
- publishTime()
- publishTime()
+ dt = now()
+ milisecs = inMilliseconds (dt - clock.midnight)
+ hexsecs = (milisecs div milisecPerHexsec) and 0xFF_FF
+ hexStr = toHex(hexsecs shr 12, 1) & "_" & toHex(hexsecs shr 4, 2) & "_" & toHex(hexsecs, 1)
+ replace(turn, clock.ds, clock.timeHandle, TonalTime(num: hexsecs, hex: hexStr))
+
+proc loop(clock: Clock) {.asyncio.} =
+ let fd = newHexSecTimer()
+ while true:
+ update(clock)
+ wait(FD fd, Read)
+ var n: uint64
+ discard read(fd, addr n, sizeof n)
+
+runActor("tonaltime") do (turn: var Turn):
+ resolveEnvironment(turn) do (turn: var Turn; ds: Cap):
+ during(turn, ds, ?:Args) do (ds: Cap, lat: float, lon: float):
+ let
+ horizon = horizonTimes(lon, lat, now())
+ dayDur = horizon.sundown - horizon.sunrise
+ noon = horizon.sunrise + (dayDur div 2)
+ midnight = noon - initDuration(hours = 12)
+
+ discard publish(turn, ds, Sunrise(s: $horizon.sunrise))
+ discard publish(turn, ds, Sunset(s: $horizon.sundown))
+ discard publish(turn, ds, Noon(s: $noon))
+ discard publish(turn, ds, Midnight(s: $midnight))
+ # TODO: recalculate every 12 hours
+
+ discard trampoline:
+ whelp Clock(facet: turn.facet, ds: ds, midnight: midnight).loop()