Update: after manually clearing dispatcher's `callbacks` and `timers` and
manually calling a GC the memory is properly freed, even when the `cycle`
coroutine is still pending. So the question is: why do I have to do this
manually? Shouldn't this be done automatically when the thread finishes?
The properly working code is below:
import std/asyncdispatch
import HeapQueue, deques
type MyObj = object
value: ptr int
proc `=destroy`(x: MyObj) =
if x.value == nil:
return
dealloc(cast[pointer](x.value))
echo "memory deallocated"
proc newMyObj(x: int): MyObj =
result.value = cast[ptr int](alloc0(100_000_000*sizeof(int)))
echo "memory allocated"
let p = cast[ptr UncheckedArray[int]](result.value)
for i in 0..<100_000_000:
p[i] = x + i
proc cycler(x: ref MyObj) {.async.} =
while true:
x.value[] += 1
echo x.value[]
await sleepAsync(200)
proc main_async() {.async.} =
let x = new(MyObj)
x[] = newMyObj(3)
let fut = cycler(x)
await sleepAsync(1000)
proc main() {.thread.} =
echo "thread started"
waitFor(main_async())
echo "thread finished"
let p = getGlobalDispatcher()
p.callbacks.clear()
p.timers.clear()
GC_fullCollect()
while true:
var th = Thread[void]()
createThread(th, main)
joinThreads(th)
Run