arc/orc leak?
zevv opened this issue · comments
In the little program below two continuations are created, both put on a little work queue. One by doing a dequeue push directly, the other by calling a proc that does exactly that.
One leaks, the other does not.
import cps
import std/[deques]
# Basic CPS stuff
type
C* = ref object of Continuation
evq*: Evq
Evq* = ref object
work*: Deque[C]
# An object type with destructor
type
ThingObj = object
name: string
Thing = ref ThingObj
proc `=destroy`(t: var ThingObj) =
echo "destroyed ", t.name
# Push proc. Part of the problem? Change this proc into a template an the issue goes away.
proc push*(evq: Evq, c: C) =
evq.work.addLast c
# Happy little CPS proc creating a Thing
proc flop(name: string) {.cps:C.} =
echo "make ", name
var t = Thing(name: name)
echo "done ", name
# Some event queue
var myevq = Evq()
# This thing will leak
myevq.push whelp flop("one")
# But this thing will not
myevq.work.addLast whelp flop("two")
# Pump my queue
while true:
while myevq.work.len > 0:
discard trampoline(myevq.work.popFirst)
Expected output:
make one
done one
destroyed one
make two
done two
destroyed two
Actual output:
make one
done one
make two
done two
destroyed two
sinking in the push works, but @Clyybber convinced me recently that I don't know a damned thing about how sink
is supposed to work.
So, that's just a Nim bug, right? right?!
Nim Compiler Version 1.5.1 [Linux: amd64]
Compiled at 2021-07-02
Copyright (c) 2006-2021 by Andreas Rumpf
git hash: 60eac79f7f0478565a24ff423aa52ab53527d153
active boot switches: -d:release -d:danger
Not a bug, the scope in which you do whelp flop("one")
never closes, so the destructor for the result from that expression never get's called. For myevq.work.addLast whelp flop("two")
you get the destructor call because you pass ownership directly from the whelp
to myevq.work
because addLast
takes a sink param.