Will it work as intended?
type
Unsafe = ptr UnsafeObj
UnsafeObj = array[1_000, byte]
Safe[T] = ref SafeObj[T]
SafeObj[T] = object
data: T
# Foreign interface
proc malloc(size: csize): pointer {.importc: "malloc", header: "<stdio.h>".}
proc free(obj: pointer) {.importc: "free", header: "<stdio.h>"}
proc newUnsafe: Unsafe =
cast[Unsafe](malloc(sizeof(UnsafeObj)))
proc free(obj: Unsafe) =
free(cast[pointer](obj))
const Count = 100
var notFinalized = Count
proc free(obj: Safe) =
if obj.data != nil:
dec(notFinalized)
free(obj.data)
obj.data = nil
proc newSafe[T](): Safe[T] =
new result, free
result.data = newUnsafe()
converter toUnsafe(safe: Safe): Unsafe =
safe.data
proc main =
var safe: array[Count, Safe[Unsafe]]
for i in 0..safe.high:
safe[i] = newSafe[Unsafe]()
main()
GC_fullCollect()
echo notFinalized, " objects not finalized."
The code looks correct to me, but the results are somewhat surprising.
Default GC:
1 objects not finalized.
MarkAndSweep:
0 objects not finalized.
Boehm:
100 objects not finalized.
V2:
collectCycles: introduced bug E 1
5 objects not finalized.
yglukhov, -d:debug vs. -d:release also gives different output.
My results:
4 objects not finalized.
0 objects not finalized.
2 objects not finalized.
0 objects not finalized.
And 100 on Boehm, both debug and release.
Since latest update to devel this does not compile anymore!
unsafe_pointers.nim(51, 22) template/generic instantiation from here
unsafe_pointers.nim(40, 7) Error: type mismatch: got (Safe[unsafe_pointers.Unsafe], proc (obj: Unsafe){.gcsafe, locks: 0.} | proc (obj: pointer) | proc (obj: Safe))
but expected one of:
system.new(a: var ref T)
system.new(T: typedesc)
system.new(a: var ref T, finalizer: proc (x: ref T))
Exited with status 1
EDIT: Works again (as before) with
proc free[T](obj: Safe[T])=
if obj.data != nil:
dec(notFinalized)
free(obj.data)
obj.data = nil
When Count is 2^N and even (namely 0, 2, 4, 8, but not 1), all refs are freed.
(I'm using only -d:debug and the default gc.)