Files
Nim/tests/yrc/tyrc_threads.nim
2026-07-22 20:19:32 +02:00

61 lines
1.5 KiB
Nim

discard """
cmd: "nim c --mm:yrc -d:useMalloc --threads:on $file"
output: "ok"
disabled: "windows"
disabled: "freebsd"
disabled: "openbsd"
"""
# N threads each churn garbage cycles while maintaining one live ring that is
# verified continuously and replaced, plus explicit GC_runOrc collections from
# every thread. Corruption of live data trips a doAssert.
import std/typedthreads
type Node = ref object
next: Node
prev: Node
id: int
const NThreads = 4
const Iters = 30_000
proc mkRing(n, tag: int): Node =
result = Node(id: tag)
var c = result
for i in 1 ..< n:
let x = Node(id: tag + i)
c.next = x
x.prev = c
c = x
c.next = result
result.prev = c
proc checkRing(r: Node; n, tag: int) =
var c = r
for i in 0 ..< n:
doAssert c.id == tag + i, "ring corrupted!"
c = c.next
doAssert c == r, "ring not closed!"
var results: array[NThreads, int]
proc worker(tid: int) {.thread.} =
var keep = mkRing(5, tid * 1000)
for i in 0 ..< Iters:
discard mkRing(3 + (i and 7), 999999) # garbage
if (i and 255) == 0:
checkRing(keep, 5, tid * 1000)
keep = mkRing(5, tid * 1000) # old keep becomes garbage
if (i and 1023) == 0:
GC_runOrc() # explicit collections from all threads
checkRing(keep, 5, tid * 1000)
results[tid] = 1
var th: array[NThreads, Thread[int]]
for i in 0 ..< NThreads: createThread(th[i], worker, i)
joinThreads(th)
for i in 0 ..< NThreads: doAssert results[i] == 1
GC_fullCollect()
echo "ok"