Hello,
Should an async proc be expected to work within a manual Thread() ?
I'm working to parallelize an application that uses the async-based nimble module "ws" for websocket connectivity. I need to know if this is at all expected to work.
In experiments, I'm getting compiler (1.4.8) complaints such as:
Warning: 'readNimAsyncContinue' is not GC-safe as it accesses 'nameIterVar`gensym109' which is a global using GC'ed memory [GcUnsafe2]
Warning: 'read' is not GC-safe as it calls 'readNimAsyncContinue' [GcUnsafe2]
Thank you for your assistance.
Thanks. Great!
I will continue to work through the issue I have encountered.
Hi PMunch - I continue to get compiler errors when trying to use the async-based nimble package "ws" for websocket connectivity within a Thread.
For example I get the following errors from version 1.4.8 of the nim compiler
Warning: 'runAsyncNimAsyncContinue' is not GC-safe as it accesses 'nameIterVar`gensym9' which is a global using GC'ed memory [GcUnsafe2]
Warning: 'runAsync' is not GC-safe as it calls 'runAsyncNimAsyncContinue' [GcUnsafe2]
Error: 'runThr' is not GC-safe as it calls 'runAsync'
The code which results in the compile error above follows:
import ws, asyncdispatch
var wsk = waitFor newWebsocket("wss://ws.kraken.com")
proc ping() {.async.} =
while true:
await sleepAsync(6000)
echo "ping"
await wsk.ping()
proc read() {.async.} =
while true:
let str = await wsk.receiveStrPacket()
echo str
proc runAsync() {.async.} =
asyncCheck read()
asyncCheck ping()
proc runThr() {.thread.} =
asyncCheck runAsync()
runForever()
var thread: Thread
createThread(thread,runThr)
join(thread)
Hi PMunch - thanks for the suggestions - i still get the same compiler errors when moving the definition of the WebSocket variable "wsk" into "runThr()" as below:
import ws, asyncdispatch
proc ping(wsk: WebSocket) {.async.} =
while true:
await sleepAsync(6000)
echo "ping"
await wsk.ping()
proc read(wsk: WebSocket) {.async.} =
while true:
let str = await wsk.receiveStrPacket()
echo str
proc runAsync(wsk: WebSocket) {.async.} =
asyncCheck read(wsk)
asyncCheck ping(wsk)
proc runThr() {.thread.} =
var wsk = waitFor newWebsocket("wss://ws.kraken.com")
asyncCheck runAsync(wsk)
runForever()
var thread: Thread
createThread(thread,runThr)
join(thread)
The error merely moves to runThr as below:
Warning: 'runThrNimAsyncContinue' is not GC-safe as it accesses 'nameIterVar`gensym12' which is a global using GC'ed memory [GcUnsafe2]
Error: 'runThr' is not GC-safe as it calls 'runThrNimAsyncContinue'
I'm running on a Ubuntu 18.04 LTS host with version 1.4.8 of the Nim compiler and version 0.4.4 of the websocket nimble package ws. I also tested the devel version of the compiler using choosenim with the same result.
Correction - the error message is now:
Error: invalid type: 'Thread' for var
Possible option would be to start N single threaded Nim processes. And avoid using multi threading.
From my experience both threads and async are immature, and using both simultaneously should be even harder.
Hello - I found a version of the experimental code that compiles and runs without segfault as several iterations of the experiment that have not. My actual use case is more complicated, but at least this experiment shows it can work. See below:
import ws, asyncdispatch
import strformat
proc ping(wsk: WebSocket) {.async.} =
while true:
await sleepAsync(1000)
echo "ping"
await wsk.ping()
proc read(wsk: WebSocket) {.async.} =
while true:
let str = await wsk.receiveStrPacket()
echo str
proc runAsync(wsk: WebSocket) {.async.} =
asyncCheck read(wsk)
asyncCheck ping(wsk)
proc runThr(arg: int) {.thread.} =
echo &"{arg=}"
var wsk = waitFor newWebsocket("wss://ws.kraken.com")
asyncCheck runAsync(wsk)
runForever()
var thread: Thread[int]
createThread(thread,runThr,-1)
joinThread(thread)