I want to execute a proc at some specified time, but I want to be able to change this time.
So at the moment I just create a thread which sleeps the correct amount of time before it does its task, and if I want to change the time I cancel the thread and start a new one.
But I dont realy want to create a new thread every time. So is there a better way of achieving this? (it may be linux specific)
thanks in advance, chol
I was looking into this myself a bit and stumbled into std/asyncdispatch .
This sounds extremely like wanting to do the equivalent of a setTimeout in JS (and we do have equivalents in std/dom).
For nim on its own I only found addTimer (https://nim-lang.org/docs/asyncdispatch.html#addTimer%2Cint%2Cbool%2CCallback) Couldn't get that to work for me and I have no deeper understanding of async outside of what you learn with JS (and what builds on top of the async story in JS such as RXJS).
libev and libevent both seem to have a timeout event it can handle.
You can either use them, or look at how they done it and do it yourself:
http://www.wangafu.net/~nickm/libevent-book/Ref4_event.html http://cvs.schmorp.de/libev/README
Another option is to use the 'at' linux tool - https://man7.org/linux/man-pages/man1/at.1p.html
at, batch, atq, atrm - queue, examine, or delete jobs for later execution
A couple fun examples allowed by extended POSIX.2 timespec:
at now + 1 hour <<< "touch ~/file"
at teatime 23-08-23 <<< "touch ~/file"
at 4pm thursday + 10 minutes <<< "touch ~/file"
But I dont realy want to create a new thread every time. So is there a better way of achieving this? (it may be linux specific)
Make the proc is always running the background as a dedicated thread but lock it to save the cpu loop and only continue if the lock receiving signal.
For example here:
import std/[locks, strformat, times, threadpool, os]
var
chan: Channel[string]
cond: Cond
lock: Lock
let startTime = now()
initLock lock
initCond cond
chan.open
proc bgExec {.thread.} =
while true:
let data = tryRecv chan
if data.dataAvailable:
if data.msg == "": break
echo fmt"'{data.msg}' at duration {now() - startTime} from {startTime}"
continue
cond.wait lock
template runit(msg: string) =
chan.send msg
cond.signal
proc main {.thread.} =
runit "start"
sleep 200
runit "after 200 ms"
sleep 100
runit "after 300 ms"
sleep 200
runit "after 500 ms"
runit "stop"
runit ""
spawn bgExec()
spawn main()
sync()
In this example, channel is used to illustrate the stream of "what you want to execute" but it can be anything. The key part is the continue, condition.wait(lock) and condition.signal()