blob: e67beb513d15432ea63ae994ceedb67074666110 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
discard """
outputsub: "true"
disabled: "32bit"
"""
type
TFoo* = object
id: int
fn: proc() {.closure.}
var foo_counter = 0
var alive_foos = newseq[int](0)
when defined(gcDestructors):
proc `=destroy`(some: TFoo) =
alive_foos.del alive_foos.find(some.id)
# TODO: fixme: investigate why `=destroy` requires `some.fn` to be `gcsafe`
# the debugging info below came from `symPrototype` in the liftdestructors
# proc (){.closure, gcsafe.}, {tfThread, tfHasAsgn, tfCheckedForDestructor, tfExplicitCallConv}
# var proc (){.closure, gcsafe.}, {tfHasGCedMem}
# it worked by accident with var T destructors because in the sempass2
#
# let argtype = skipTypes(a.typ, abstractInst) # !!! it does't skip `tyVar`
# if argtype.kind == tyProc and notGcSafe(argtype) and not tracked.inEnforcedGcSafe:
# localError(tracked.config, n.info, $n & " is not GC safe")
{.cast(gcsafe).}:
`=destroy`(some.fn)
else:
proc free*(some: ref TFoo) =
#echo "Tfoo #", some.id, " freed"
alive_foos.del alive_foos.find(some.id)
proc newFoo*(): ref TFoo =
when defined(gcDestructors):
new result
else:
new result, free
result.id = foo_counter
alive_foos.add result.id
inc foo_counter
for i in 0 ..< 10:
discard newFoo()
for i in 0 ..< 10:
let f = newFoo()
f.fn = proc =
echo f.id
GC_fullcollect()
echo alive_foos.len <= 3
|