Hello together,
i think the "problem" is not a real problem and perhaps it is easy - but i don't get it :(
the situation: from my main-nim module (main.nim) i call a procedure in a module mymodule.nim. The procedure takes some arguments and do some calculations in a for loop. the result is returned in an object.
The calculation's duration can go up to 4 minutes so far - thats ok - a lot of data...
What i wanna do is, to inform the user about the progress - so that i can see, how far the calculations are done. The idea is, to divide the for-loop counter modulo by 100, and the valu is 0 (zero) => inform the procedure-caller with the current value of th forloop counter, so that the valu can be displayed for the user.
but i don't get in the ring :( I've read the docs and my plan is to use threads and a channel:
But it seems - this does not work the way i thought: can anybody give me a hint please?
Here's the code:
main.nim
import std/[os,strformat]
import mymodule
proc callBlockingProc(n, m: int): MyObj =
chan.open()
result = createThread(calculator, doSomeCalculations, n, m)
# result = doSomeCalculations(n,m)
while true:
let i: int = chan.recv()
echo "done " & $i & " values so far..."
when isMainModule:
echo "start playing with threads..."
let mo = callBlockingProc(80,3)
echo len(mo.importantData)
mymodule.nim
import std/[os]
type
MyObj* = object
importantData*: seq[int]
var chan*: Channel[int]
var calculator*: Thread[(int, int)]
proc doSomeCalculations*(i, k: int): MyObj {.thread.} =
result = MyObj()
result.importantData = @[]
for j in 1..i:
sleep(j*10)
result.importantData.add(j*k)
if (j mod 10) == 0:
chan.send(j)
Any reason to not just do:
proc doSomeCalculations*(i, k: int): MyObj =
result = MyObj()
result.importantData = @[]
for j in 1..i:
sleep(j*10)
result.importantData.add(j*k)
if (j mod 10) == 0:
echo "done " & $i & " values so far...
Without threads and channels?
I've read the docs and my plan is to use threads and a channel
I can't find any (atleast up-to-date) docs on either Channel or Thread. In most cases - it means that feature is not well supported and you should try something else. See malebolgia or weave for good multithreading library.
Anyway, here is something I pieced out that could help you get an idea how to use channels in Nim. Note: I'm the opposite of expert on this topic, I've spent literally 30 minutes just now to make it work, but it does work =D :
import std/os
var T: Thread[void]
var chan: Channel[int]
proc doCalc() {.thread.} = # note that doCalc doesn't return anything
for i in 1..100:
sleep(100) # imitates some work
chan.send(i)
proc main =
chan.open()
T.createThread(doCalc)
while true:
let progress = chan.recv()
echo progress
if progress >= 100:
break
chan.close()
main()
Or you could also use async for that.
thanx for reading my question to your answers:
a.) the reason why i do not use the "echo" directly in the procedure is, because i've stripped down the "real application" to a simple use case (i thought ;) ). The real application is a gui which is calling the "callBlockingProc"
b.) the "docs" i ment:
what do you mean with "they are not up to date"?
c.) using weave or malebolgia: i've found these modules by my selfe, but i thought, for such a simple case as mine - i would't install an extra module...
d.) thx for your example - looks like a stripped down example as descriped here:
I've also used this example - and as you already mentioned in your code:
...and for such a use case, there is no example - and so far as i got - you can see in my post ;)
thx again and have a nice day!