nim 提供了 spawn
簡化工作在 thread 間的分派, 例子如下
import os, threadpool
proc task(): string =
sleep(3 * 1000)
result = "hello"
var v = spawn task()
echo "Wait for task..."
echo ^v
spawn
是由threadpoll
module 提供spawn
後是 proc 的呼叫- 傳回的是
FlowVar[T]
(或是void
) 的類型 - 在 task 結束後,
v
(type 為FlowVar[string]
) 會被放入"hellow"
- 可用
^
operator 對v
進行等待
Thread 間要通訊的話, 可用 Channel[T]
import os, threadpool
var c: Channel[int]
c.open()
proc task(): string =
echo "Receiving delay ms..."
let delay = c.recv()
echo "Go delay ms: ", delay
sleep(delay)
result = "hello"
var v = spawn task()
echo "Delay 3000ms then order"
sleep(3000)
c.send(3000)
echo "Wait for task..."
echo ^v
因為 spawn
呼叫的 proc 不能有 var
類型的 argument (send()
及 recv()
時用的參數類型為 var
的, 所以傳入非 var
給這裡的 task()
並沒有什麼用處), 所以這裡是通過 global variable 共享 c
(type 為 Channel[int]
), 並用 send()
及 recv()
送收訊息.
如果, 有多個 spawn 出去的 task 需要等待, 可用 sync()
完成 - 當然, 會 block 目前的 thread.
雖說 spawn
呼叫的 proc 為了 thread safty 不能有 var
argument, 但可用 ptr
做為 workaround
import os, threadpool
proc task(c: ptr Channel[int]): string =
echo "Receiving delay ms..."
let delay = c[].recv()
echo "Go delay ms: ", delay
sleep(delay)
result = "hello"
var c: Channel[int]
c.open()
var v = spawn task(addr c)
echo "Delay 3000ms then order"
sleep(3000)
c.send(3000)
echo "Wait for task..."
echo ^v
要注意的是
Channel[T]
是 thread safe 的, 所以通過ptr
argument 共享沒升麼問題- 因為傳入
task()
的 channel 是ptr
類型的, 所以需要配合[]
進行 dereference - nim 不會追蹤
ptr
的生命週期, 所以要確保被共享的Channel[T]
在使用期間不被 GC 回收 - 要不, 就得配合
createShared()
將 channel 配置在 shared heap 上, 這樣才能被任意的 threadfreeShared()