concrete LeakTest { @type run () -> () } define LeakTest { @value Vector memory run () { if (Argv.global().size() != 2) { \ message() } elif (Argv.global().readAt(1) == "race") { \ runWith(1000,0) \ LazyStream.new() .append("no race conditions this time\n") .writeTo(SimpleOutput.stderr()) } elif (Argv.global().readAt(1) == "leak") { \ runWith(100,0) } elif (Argv.global().readAt(1) == "forever") { \ runWith(10000000,1024*1024) } else { \ message() } } @type message () -> () message () { fail(Argv.global().readAt(0) + " [race|leak|forever]") } @type runWith (Int,Int) -> () runWith (iterations,size) { Int threads <- Ranges:max(3,$ExprLookup[CPU_CORE_COUNT]$-1) ReadAt barriers <- EnumeratedBarrier.new(threads+1) traverse (Counter.zeroIndexed(iterations) -> Int i) { \ doIteration(i,size,barriers) \ doIteration(i,size,barriers) } } @type doIteration<#f> #f defines ThreadFactory (Int,Int,ReadAt) -> () doIteration (i,size,barriers) { \ LazyStream.new() .append(typename<#f>()) .append(": iteration ") .append(i) .append("\n") .writeTo(SimpleOutput.stderr()) optional LeakTest original <- LeakTest{ Vector:createSize(size) } Vector threads <- Vector:create() traverse (Counter.zeroIndexed(barriers.size()-1) -> Int j) { \ threads.push(ProcessThread.from(#f.create(original,barriers.readAt(j+1))).start()) } \ barriers.readAt(0).wait() original <- empty traverse (threads.defaultOrder() -> Thread thread) { \ thread.join() } } } @type interface ThreadFactory { create (optional LeakTest,BarrierWait) -> (Routine) } concrete LastReference { defines ThreadFactory } define LastReference { $ReadOnly[copy,barrier]$ refines Routine @value weak LeakTest copy @value BarrierWait barrier create (copy,barrier) { return LastReference{ copy, barrier } } run () { \ barrier.wait() \ strong(copy) } } concrete Chaos { defines ThreadFactory } define Chaos { $ReadOnly[barrier]$ refines Routine @value weak LeakTest copy @value BarrierWait barrier create (copy,barrier) { return Chaos{ copy, barrier } } run () { weak LeakTest copy1 <- empty weak LeakTest copy2 <- empty weak LeakTest copy3 <- empty weak LeakTest copy4 <- empty weak LeakTest copy5 <- empty \ barrier.wait() copy1 <- copy copy2 <- copy1 copy3 <- copy1 copy <- empty copy4 <- strong(copy2) copy1 <- strong(copy3) copy2 <- empty copy3 <- empty } }