Created
June 4, 2015 17:27
-
-
Save fowlmouth/94ee8e79e06b22b28959 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
discard """ | |
a generic gc test? | |
what operations are required | |
- an expression that saves a ref must increment its reference | |
- an expression that replaces a ref must decrement the ref it held previously | |
- a gc-safe type decrements held references upon destruction (manual or automatic) | |
""" | |
template gcTest* (body: untyped): stmt {. dirty, immediate } = | |
template exprIncsRef (rf, xpr: untyped): stmt = | |
{.line: instantiationInfo() }: | |
block: | |
let rc = getRefCount(rf) | |
block: xpr | |
GC_fullCollect() | |
do_assert( | |
not rf.isNil and getRefCount(rf) == rc+1, | |
"expression did not incref: "& astToStr(xpr) ) | |
template exprDecsRef (rf, xpr: untyped): stmt = | |
{.line: instantiationInfo() }: | |
block: | |
do_assert(not rf.isNil, "reference is not valid! "& $instantiationInfo()) | |
let old_rf = rf | |
let old_rc = getRefCount(rf) | |
block: xpr | |
GC_fullCollect() | |
do_assert( | |
getRefCount(old_rf) == old_rc-1, | |
"expression did not dec ref "& astToStr(xpr) | |
) | |
template exprReplacesRef (newRf, oldRf, xpr: untyped): stmt = | |
{.line: instantiationInfo() }: | |
exprIncsRef(newRf): | |
exprDecsRef(oldRf): | |
xpr | |
template exprDoesntRef (oldRf, xpr: untyped): stmt = | |
{.line: instantiationInfo() }: | |
let old_rc = getRefCount(oldRf) | |
xpr | |
GC_fullCollect() | |
do_assert getRefCount(oldRf) == old_rc, "expression did not keep ref "& astToStr(xpr) | |
try: | |
body | |
except: | |
echo("Unhandled exception: " & getCurrentExceptionMsg()) | |
echo getCurrentException().getStackTrace() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## gc test for ref object components | |
import cmodel, std_test, gctester | |
type GC1 = ref object | |
defPrimitiveComponent(GC1, GC1) | |
var global_o: GC1 | |
gcTest: | |
proc x = | |
var my = aggxGC1.instantiate | |
block: | |
var my_o: GC1 | |
new(my_o) do (some:GC1): echo"Freeing GC1" | |
exprIncsRef(my_o): | |
my.findData(GC1)[] = my_o | |
exprDecsRef(my_o): | |
my.findDataM(GC1) = nil.GC1 | |
assert getRefCount(my_o) == 0 | |
exprIncsRef(my_o): | |
global_o = my_o | |
exprIncsRef(my_o): | |
my.findData(GC1)[] = my_o | |
assert getRefCount(my_o) == 2 | |
assert global_o.isNil | |
x() | |
GCfullCollect() | |
## after freeing, the only reference should be global_o | |
assert getRefCount(global_o) == 1, "invalid ref count for global_o:"& $getRefCount(global_o) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## test that storing Objects in slots of components is gc safe | |
import cmodel, std_test, gctester | |
gcTest: | |
let my_comp = dynaComponent("my_comp", "child1", "child2") | |
let aggx = aggregate(my_comp) | |
let my1 = aggx.instantiate() | |
let my2 = aggx.instantiate() | |
exprIncsRef(my1): | |
discard my2.send("child1:", my1) | |
exprReplacesRef(my2, my1): | |
discard my2.send("child1:", my2) | |
exprDecsRef(my2): | |
discard my2.send("child1:", nil.Object) | |
assert getRefCount(my1) == 0 | |
assert getRefCount(my2) == 0 | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# objects stored in closures are destroyed with the closure | |
import cmodel, std_test, gctester | |
type GC1 = ref object | |
defPrimitiveComponent(GC1, GC1) | |
gcTest: | |
let my_o = instantiate aggregate(typeComponent(GC1)) | |
proc mkClosure(o:Object): proc(): Object = | |
return proc(): Object = | |
return o | |
var p: proc(): Object | |
exprIncsRef(my_o): | |
p = mkClosure(my_o) | |
assert getRefCount(my_o) == 1 | |
assert p() == my_o | |
exprDecsRef(my_o): | |
p = nil | |
assert getRefCount(my_o) == 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment