Since I’ve been experimenting with related features, I’ll post something which works on yesterday’s nightly (with PARTR):
using Base.Threads
const ctr=Ref(0)
const amidone=Ref(false)
function upd(t)
ctr[] += 1
end
t = Timer(upd, 1; interval=1)
function periodicjob()
while isopen(t)
wait(t)
c = ctr[]
println("running $c")
end
end
function crunch()
for i=1:1000
rand(1000, 1000) * rand(1000, 1000)
end
println("loop done")
amidone[] = true
end
if nthreads() == 1
crunch()
else
@threads for j=1:2
id = threadid()
if id == 1
tHdl = @task periodicjob()
schedule(tHdl)
else
cHdl = @task crunch()
schedule(cHdl)
end
end
end
# N.B.: controller must stay alive
while !amidone[]
sleep(0.1)
end
close(t)
IIUC, it is important that the thread 1 code yield (or be trivial). The periodicjob
may need to run on thread 1 (or on the thread where its Timer lives?) for consistent timing.
Experiments with more substantial subsidiary tasks suggest that the overhead is modest, but I haven’t thought of a good way to verify that the primary (crunch
) task is truly continuous (when BLAS is limited to one thread).