diff options
Diffstat (limited to 'tests/threads')
-rw-r--r-- | tests/threads/nim.cfg | 1 | ||||
-rw-r--r-- | tests/threads/t7172.nim | 34 | ||||
-rw-r--r-- | tests/threads/t8535.nim | 30 | ||||
-rw-r--r-- | tests/threads/tactors.nim | 13 | ||||
-rw-r--r--[-rwxr-xr-x] | tests/threads/threadex.nim | 22 | ||||
-rw-r--r-- | tests/threads/tjsthreads.nim | 6 | ||||
-rw-r--r-- | tests/threads/tmanyjoin.nim | 31 | ||||
-rw-r--r-- | tests/threads/tmembug.nim | 51 | ||||
-rw-r--r-- | tests/threads/tonthreadcreation.nim | 26 | ||||
-rw-r--r-- | tests/threads/tracy_allocator.nim | 26 | ||||
-rw-r--r-- | tests/threads/trecursive_actor.nim | 19 | ||||
-rw-r--r-- | tests/threads/treusetvar.nim | 29 | ||||
-rw-r--r--[-rwxr-xr-x] | tests/threads/tthreadanalysis.nim | 15 | ||||
-rwxr-xr-x | tests/threads/tthreadanalysis2.nim | 52 | ||||
-rw-r--r-- | tests/threads/tthreadanalysis3.nim | 51 | ||||
-rw-r--r--[-rwxr-xr-x] | tests/threads/tthreadheapviolation1.nim | 12 | ||||
-rw-r--r-- | tests/threads/tthreadvars.nim | 79 | ||||
-rw-r--r-- | tests/threads/ttryrecv.nim | 36 |
18 files changed, 376 insertions, 157 deletions
diff --git a/tests/threads/nim.cfg b/tests/threads/nim.cfg new file mode 100644 index 000000000..b81c89721 --- /dev/null +++ b/tests/threads/nim.cfg @@ -0,0 +1 @@ +threads:on diff --git a/tests/threads/t7172.nim b/tests/threads/t7172.nim new file mode 100644 index 000000000..87e89417b --- /dev/null +++ b/tests/threads/t7172.nim @@ -0,0 +1,34 @@ +discard """ + disabled: i386 + output: ''' +In doStuff() +In initProcess() +TEST +initProcess() done +Crashes before getting here! +''' + joinable: false +""" + +import std/os +import std/typedthreads + +proc whatever() {.thread, nimcall.} = + echo("TEST") + +proc initProcess(): void = + echo("In initProcess()") + var thread: Thread[void] + createThread(thread, whatever) + joinThread(thread) + echo("initProcess() done") + +proc doStuff(): void = + echo("In doStuff()") + # ... + initProcess() + sleep(500) + # ... + echo("Crashes before getting here!") + +doStuff() diff --git a/tests/threads/t8535.nim b/tests/threads/t8535.nim new file mode 100644 index 000000000..a4296df11 --- /dev/null +++ b/tests/threads/t8535.nim @@ -0,0 +1,30 @@ +discard """ + disabled: i386 + output: '''0 +hello''' +""" + +type + CircAlloc*[Size: static[int], T] = tuple + baseArray: array[Size,T] + index: uint16 + +type + Job = object of RootObj + +var foo {.threadvar.}: CircAlloc[1, Job] + +when true: + echo foo.index + + +# bug #10795 +import asyncdispatch +import threadpool + +proc f1() = + waitFor sleepAsync(20) + echo "hello" + +spawn f1() +sync() diff --git a/tests/threads/tactors.nim b/tests/threads/tactors.nim deleted file mode 100644 index 45a03ebb7..000000000 --- a/tests/threads/tactors.nim +++ /dev/null @@ -1,13 +0,0 @@ -discard """ - outputsub: "150" -""" - -import actors - -var - pool: TActorPool[int, void] -createActorPool(pool) -for i in 0 .. < 300: - pool.spawn(i, proc (x: int) {.thread.} = echo x) -pool.join() - diff --git a/tests/threads/threadex.nim b/tests/threads/threadex.nim index 0360c8c04..90119aee7 100755..100644 --- a/tests/threads/threadex.nim +++ b/tests/threads/threadex.nim @@ -1,21 +1,25 @@ discard """ - outputsub: "All rights reserved." + disabled: i386 + outputsub: "Just a simple text for test" """ type TMsgKind = enum mLine, mEof - TMsg = object {.pure, final.} + TMsg = object case k: TMsgKind - of mEof: nil + of mEof: discard of mLine: data: string var - producer, consumer: TThread[void] - chan: TChannel[TMsg] + producer, consumer: Thread[void] + chan: Channel[TMsg] printedLines = 0 + prodId: int + consId: int proc consume() {.thread.} = + consId = getThreadId() while true: var x = recv(chan) if x.k == mEof: break @@ -23,16 +27,17 @@ proc consume() {.thread.} = atomicInc(printedLines) proc produce() {.thread.} = + prodId = getThreadId() var m: TMsg - var input = open("readme.txt") + var input = open("tests/dummy.txt") var line = "" while input.readLine(line): m.data = line chan.send(m) close(input) - m.k = mEof + m = TMsg(k: mEof) chan.send(m) - + open(chan) createThread[void](consumer, consume) createThread[void](producer, produce) @@ -40,5 +45,6 @@ joinThread(consumer) joinThread(producer) close(chan) +doAssert prodId != consId echo printedLines diff --git a/tests/threads/tjsthreads.nim b/tests/threads/tjsthreads.nim new file mode 100644 index 000000000..5122c9cd6 --- /dev/null +++ b/tests/threads/tjsthreads.nim @@ -0,0 +1,6 @@ +discard """ + targets: "js" + matrix: "--threads:on" +""" + +echo 123 diff --git a/tests/threads/tmanyjoin.nim b/tests/threads/tmanyjoin.nim new file mode 100644 index 000000000..af5bc460e --- /dev/null +++ b/tests/threads/tmanyjoin.nim @@ -0,0 +1,31 @@ +discard """ + disabled: i386 + outputsub: "129" +""" + +import os, locks + +type + MarkerObj = object + lock: Lock + counter: int + Marker = ptr MarkerObj + +const + ThreadsCount = 129 + SleepTime = 250 + +proc worker(p: Marker) {.thread.} = + acquire(p.lock) + inc(p.counter) + release(p.lock) + sleep(SleepTime) + +var p = cast[Marker](allocShared0(sizeof(MarkerObj))) +initLock(p.lock) +var ts = newSeq[Thread[Marker]](ThreadsCount) +for i in 0..<ts.len: + createThread(ts[i], worker, p) + +joinThreads(ts) +echo p.counter diff --git a/tests/threads/tmembug.nim b/tests/threads/tmembug.nim new file mode 100644 index 000000000..3618f0ecc --- /dev/null +++ b/tests/threads/tmembug.nim @@ -0,0 +1,51 @@ + +import std / [atomics, strutils, sequtils] + +type + BackendMessage* = object + field*: seq[int] + +var + chan1: Channel[BackendMessage] + chan2: Channel[BackendMessage] + +chan1.open() +chan2.open() + +proc routeMessage*(msg: BackendMessage) = + discard chan2.trySend(msg) + +var + recv: Thread[void] + stopToken: Atomic[bool] + +proc recvMsg() = + while not stopToken.load(moRelaxed): + let resp = chan1.tryRecv() + if resp.dataAvailable: + routeMessage(resp.msg) + echo "child consumes ", formatSize getOccupiedMem() + +createThread[void](recv, recvMsg) + +const MESSAGE_COUNT = 100 + +proc main() = + let msg: BackendMessage = BackendMessage(field: (0..500).toSeq()) + for j in 0..0: #100: + echo "New iteration" + + for _ in 1..MESSAGE_COUNT: + chan1.send(msg) + echo "After sending" + + var counter = 0 + while counter < MESSAGE_COUNT: + let resp = recv(chan2) + counter.inc + echo "After receiving ", formatSize getOccupiedMem() + + stopToken.store true, moRelaxed + joinThreads(recv) + +main() diff --git a/tests/threads/tonthreadcreation.nim b/tests/threads/tonthreadcreation.nim new file mode 100644 index 000000000..61529477d --- /dev/null +++ b/tests/threads/tonthreadcreation.nim @@ -0,0 +1,26 @@ +discard """ + disabled: i386 + matrix: "--mm:refc; --mm:orc --deepcopy:on" + output: '''some string here +dying some string here''' +""" + +var + someGlobal: string = "some string here" + perThread {.threadvar.}: string + +proc threadDied() {.gcsafe.} = + echo "dying ", perThread + +proc foo() {.thread.} = + onThreadDestruction threadDied + {.gcsafe.}: + deepCopy(perThread, someGlobal) + echo perThread + +proc main = + var t: Thread[void] + createThread[void](t, foo) + t.joinThread() + +main() diff --git a/tests/threads/tracy_allocator.nim b/tests/threads/tracy_allocator.nim new file mode 100644 index 000000000..f3b39f4dc --- /dev/null +++ b/tests/threads/tracy_allocator.nim @@ -0,0 +1,26 @@ +discard """ + disabled: i386 + output: '''true''' +""" + +var somethingElse {.threadvar.}: ref string + +type MyThread = Thread[void] + +proc asyncThread() {.thread.} = + new somethingElse + +var threads = newSeq[ptr Thread[void]](8) + +for c in 1..1_000: + #echo "Test " & $c + for i in 0..<threads.len: + var t = cast[ptr Thread[void]](alloc0(sizeof(MyThread))) + threads[i] = t + createThread(t[], asyncThread) + + for t in threads: + joinThread(t[]) + dealloc(t) + +echo "true" diff --git a/tests/threads/trecursive_actor.nim b/tests/threads/trecursive_actor.nim deleted file mode 100644 index e2774704c..000000000 --- a/tests/threads/trecursive_actor.nim +++ /dev/null @@ -1,19 +0,0 @@ -discard """ - outputsub: "0" -""" - -import actors - -var - a: TActorPool[int, void] -createActorPool(a) - -proc task(i: int) {.thread.} = - echo i - if i != 0: a.spawn (i-1, task) - -# count from 9 till 0 and check 0 is somewhere in the output -a.spawn(9, task) -a.join() - - diff --git a/tests/threads/treusetvar.nim b/tests/threads/treusetvar.nim new file mode 100644 index 000000000..f0337801a --- /dev/null +++ b/tests/threads/treusetvar.nim @@ -0,0 +1,29 @@ +discard """ + disabled: i386 + outputsub: "65" +""" + +import locks + +type + MarkerObj = object + lock: Lock + counter: int + Marker = ptr MarkerObj + +const + ThreadsCount = 65 + +proc worker(p: Marker) {.thread.} = + acquire(p.lock) + inc(p.counter) + release(p.lock) + +var p = cast[Marker](allocShared0(sizeof(MarkerObj))) +initLock(p.lock) + +for i in 0..(ThreadsCount - 1): + var thread: Thread[Marker] + createThread(thread, worker, p) + joinThread(thread) +echo p.counter diff --git a/tests/threads/tthreadanalysis.nim b/tests/threads/tthreadanalysis.nim index 4edd51025..7fc3593c8 100755..100644 --- a/tests/threads/tthreadanalysis.nim +++ b/tests/threads/tthreadanalysis.nim @@ -1,18 +1,19 @@ discard """ - outputsub: "101" - cmd: "nimrod cc --hints:on --threads:on $# $#" + errormsg: "'threadFunc' is not GC-safe" + line: 38 + cmd: "nim $target --hints:on --threads:on $options $file" """ import os var - thr: array [0..5, TThread[tuple[a, b: int]]] + thr: array[0..5, Thread[tuple[a, b: int]]] -proc doNothing() = nil +proc doNothing() = discard type PNode = ref TNode - TNode = object {.pure.} + TNode {.pure.} = object le, ri: PNode data: string @@ -34,9 +35,9 @@ proc echoLeTree(n: PNode) = echo it.data it = it.le -proc threadFunc(interval: tuple[a, b: int]) {.thread.} = +proc threadFunc(interval: tuple[a, b: int]) {.thread.} = doNothing() - for i in interval.a..interval.b: + for i in interval.a..interval.b: var r = buildTree(i) echoLeTree(r) # for local data echoLeTree(root) # and the same for foreign data :-) diff --git a/tests/threads/tthreadanalysis2.nim b/tests/threads/tthreadanalysis2.nim deleted file mode 100755 index 07f0e61fd..000000000 --- a/tests/threads/tthreadanalysis2.nim +++ /dev/null @@ -1,52 +0,0 @@ -discard """ - file: "tthreadanalysis2.nim" - line: 42 - errormsg: "write to foreign heap" - cmd: "nimrod cc --hints:on --threads:on $# $#" -""" - -import os - -var - thr: array [0..5, TThread[tuple[a, b: int]]] - -proc doNothing() = nil - -type - PNode = ref TNode - TNode = object {.pure.} - le, ri: PNode - data: string - -var - root: PNode - -proc buildTree(depth: int): PNode = - if depth == 3: return nil - new(result) - result.le = buildTree(depth-1) - result.ri = buildTree(depth-1) - result.data = $depth - -proc echoLeTree(n: PNode) = - var it = n - while it != nil: - echo it.data - it = it.le - -proc threadFunc(interval: tuple[a, b: int]) {.thread.} = - doNothing() - for i in interval.a..interval.b: - var r = buildTree(i) - echoLeTree(r) # for local data - root = buildTree(2) # BAD! - #echoLeTree(root) # and the same for foreign data :-) - -proc main = - root = buildTree(5) - for i in 0..high(thr): - createThread(thr[i], threadFunc, (i*100, i*100+50)) - joinThreads(thr) - -main() - diff --git a/tests/threads/tthreadanalysis3.nim b/tests/threads/tthreadanalysis3.nim deleted file mode 100644 index d7a838fec..000000000 --- a/tests/threads/tthreadanalysis3.nim +++ /dev/null @@ -1,51 +0,0 @@ -discard """ - file: "tthreadanalysis3.nim" - line: 35 - errormsg: "write to foreign heap" - cmd: "nimrod cc --hints:on --threads:on $# $#" -""" - -import os - -var - thr: array [0..5, TThread[tuple[a, b: int]]] - -proc doNothing() = nil - -type - PNode = ref TNode - TNode = object {.pure.} - le, ri: PNode - data: string - -var - root: PNode - -proc buildTree(depth: int): PNode = - if depth == 3: return nil - new(result) - result.le = buildTree(depth-1) - result.ri = buildTree(depth-1) - result.data = $depth - -proc echoLeTree(n: PNode) = - var it = n - while it != nil: - echo it.data - it = it.le - -proc threadFunc(interval: tuple[a, b: int]) {.thread.} = - doNothing() - for i in interval.a..interval.b: - var r = buildTree(i) - echoLeTree(r) # for local data - echoLeTree(root) # and the same for foreign data :-) - -proc main = - root = buildTree(5) - for i in 0..high(thr): - createThread(thr[i], threadFunc, (i*100, i*100+50)) - joinThreads(thr) - -main() - diff --git a/tests/threads/tthreadheapviolation1.nim b/tests/threads/tthreadheapviolation1.nim index 7ca6f7928..379bd55e6 100755..100644 --- a/tests/threads/tthreadheapviolation1.nim +++ b/tests/threads/tthreadheapviolation1.nim @@ -1,12 +1,12 @@ discard """ - line: 12 - errormsg: "write to foreign heap" - cmd: "nimrod cc --hints:on --threads:on $# $#" + errormsg: "'horrible' is not GC-safe" + line: 11 + cmd: "nim $target --hints:on --threads:on $options $file" """ -var +var global: string = "test string" - t: TThread[void] + t: Thread[void] proc horrible() {.thread.} = global = "string in thread local heap!" @@ -16,5 +16,3 @@ proc horrible() {.thread.} = createThread[void](t, horrible) joinThread(t) - - diff --git a/tests/threads/tthreadvars.nim b/tests/threads/tthreadvars.nim new file mode 100644 index 000000000..745e3562c --- /dev/null +++ b/tests/threads/tthreadvars.nim @@ -0,0 +1,79 @@ +discard """ +disabled: i386 +output: ''' +10 +1111 +1222 +3030303 +3060606 +6060606 +6121212 +3030903 +3061206 +3031503 +3061806 +5050505 +5101010 +''' +""" + +import typetraits + +var tls1 {.threadvar.}: int +var g0: int +var g1 {.global.}: int + +proc customInc(x: var int, delta: int) = + x += delta + +customInc(tls1, 10) +echo tls1 + +proc nonGenericProc: int = + var local: int + var nonGenericTls {.threadvar.}: int + var nonGenericGlobal {.global.}: int + var nonGenericMixedPragmas {.global, threadvar.}: int + + customInc local, 1000 + customInc nonGenericTls, 1 + customInc nonGenericGlobal, 10 + customInc nonGenericMixedPragmas, 100 + + return local + nonGenericTls + nonGenericGlobal + nonGenericMixedPragmas + +proc genericProc(T: typedesc): int = + var local: int + var genericTls {.threadvar.}: int + var genericGlobal {.global.}: int + var genericMixedPragmas {.global, threadvar.}: int + + customInc local, T.name.len * 1000000 + customInc genericTls, T.name.len * 1 + customInc genericGlobal, T.name.len * 100 + customInc genericMixedPragmas, T.name.len * 10000 + + return local + genericTls + genericGlobal + genericMixedPragmas + +echo nonGenericProc() +echo nonGenericProc() + +echo genericProc(int) +echo genericProc(int) + +echo genericProc(string) +echo genericProc(string) + +proc echoInThread[T]() {.thread.} = + echo genericProc(T) + echo genericProc(T) + +proc newEchoThread(T: typedesc) = + var t: Thread[void] + createThread(t, echoInThread[T]) + joinThreads(t) + +newEchoThread int +newEchoThread int +newEchoThread float + diff --git a/tests/threads/ttryrecv.nim b/tests/threads/ttryrecv.nim new file mode 100644 index 000000000..fcff94e78 --- /dev/null +++ b/tests/threads/ttryrecv.nim @@ -0,0 +1,36 @@ +discard """ + matrix: "--mm:refc" + outputsub: "channel is empty" +""" + +# bug #1816 + +from random import rand +from os import sleep + +type PComm = ptr Channel[int] + +proc doAction(outC: PComm) {.thread.} = + for i in 0 ..< 5: + sleep(rand(50)) + send(outC[], i) + +var + thr: Thread[PComm] + chan: Channel[int] + +open(chan) +createThread[PComm](thr, doAction, addr(chan)) + +while true: + let (flag, x) = tryRecv(chan) + if flag: + echo("received from chan: " & $x) + else: + echo "channel is empty" + break + +echo "Finished listening" + +joinThread(thr) +close(chan) |