nim-works / cps

Continuation-Passing Style for Nim 🔗

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.