Skip to content

Instantly share code, notes, and snippets.

@fowlmouth
Created June 11, 2015 21:09
Show Gist options
  • Save fowlmouth/7719641ed8052777701d to your computer and use it in GitHub Desktop.
Save fowlmouth/7719641ed8052777701d to your computer and use it in GitHub Desktop.
## 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
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()
import cmodel
GC_fullCollect()
template primitiveComponent* (ty:typedesc): (Component,AggregateType) =
(typeComponent(ty), aggregate(typeComponent(ty)))
template defPrimitiveComponent*(n,comp: untyped): stmt =
let (`cx n`*{.inject.}, `aggx n`*{.inject.}) = primitiveComponent(comp)
`cx n`.name = astToStr(n)
proc `obj n`* (some: `comp`): Object =
result = `aggx n`.instantiate
result.findDataM(comp) = some
proc asObject* (some: `comp`): Object{.inline.}=
`obj n`(some)
template setData* (ob:Object; dat:typed) =
ob.findDataM(type(dat)) = dat
proc sendAll* (ob:Object; msg:string; args:varargs[Object]): Object =
for r in ob.multicast(msg, args):
result = r
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment