summary refs log tree commit diff stats
path: root/tests/threads
diff options
context:
space:
mode:
Diffstat (limited to 'tests/threads')
-rw-r--r--tests/threads/t7172.nim34
-rw-r--r--tests/threads/t8535.nim30
-rw-r--r--tests/threads/tactors.nim13
-rw-r--r--tests/threads/tactors2.nim25
-rw-r--r--tests/threads/threadex.nim16
-rw-r--r--tests/threads/tjsthreads.nim6
-rw-r--r--tests/threads/tmanyjoin.nim31
-rw-r--r--tests/threads/tmembug.nim51
-rw-r--r--tests/threads/tonthreadcreation.nim26
-rw-r--r--tests/threads/tracy_allocator.nim26
-rw-r--r--tests/threads/trecursive_actor.nim19
-rw-r--r--tests/threads/treusetvar.nim29
-rw-r--r--tests/threads/tthreadanalysis.nim7
-rw-r--r--tests/threads/tthreadanalysis2.nim52
-rw-r--r--tests/threads/tthreadheapviolation1.nim4
-rw-r--r--tests/threads/tthreadvars.nim79
-rw-r--r--tests/threads/ttryrecv.nim7
17 files changed, 331 insertions, 124 deletions
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/tactors2.nim b/tests/threads/tactors2.nim
deleted file mode 100644
index b011ef140..000000000
--- a/tests/threads/tactors2.nim
+++ /dev/null
@@ -1,25 +0,0 @@
-discard """
-  output: "1"
-"""
-
-import actors
-
-type
-  some_type {.pure, final.} = object
-    bla: int
-
-proc thread_proc(input: some_type): some_type {.thread.} =
-  result.bla = 1
-
-proc main() =
-  var actorPool: TActorPool[some_type, some_type]
-  createActorPool(actorPool, 1)
-
-  var some_data: some_type
-
-  var inchannel = spawn(actorPool, some_data, thread_proc)
-  var recv_data = ^inchannel
-  close(inchannel[])
-  echo recv_data.bla
-
-main()
diff --git a/tests/threads/threadex.nim b/tests/threads/threadex.nim
index 442e80189..90119aee7 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: 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,14 +27,15 @@ 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)
@@ -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 a6a847a0a..7fc3593c8 100644
--- a/tests/threads/tthreadanalysis.nim
+++ b/tests/threads/tthreadanalysis.nim
@@ -1,20 +1,19 @@
 discard """
-  outputsub: "101"
   errormsg: "'threadFunc' is not GC-safe"
-  line: 39
+  line: 38
   cmd: "nim $target --hints:on --threads:on $options $file"
 """
 
 import os
 
 var
-  thr: array [0..5, Thread[tuple[a, b: int]]]
+  thr: array[0..5, Thread[tuple[a, b: int]]]
 
 proc doNothing() = discard
 
 type
   PNode = ref TNode
-  TNode = object {.pure.}
+  TNode {.pure.} = object
     le, ri: PNode
     data: string
 
diff --git a/tests/threads/tthreadanalysis2.nim b/tests/threads/tthreadanalysis2.nim
deleted file mode 100644
index 93d169f0b..000000000
--- a/tests/threads/tthreadanalysis2.nim
+++ /dev/null
@@ -1,52 +0,0 @@
-discard """
-  file: "tthreadanalysis2.nim"
-  line: 37
-  errormsg: "'threadFunc' is not GC-safe"
-  cmd: "nim $target --hints:on --threads:on $options $file"
-"""
-
-import os
-
-var
-  thr: array [0..5, Thread[tuple[a, b: int]]]
-
-proc doNothing() = discard
-
-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/tthreadheapviolation1.nim b/tests/threads/tthreadheapviolation1.nim
index 59ecb742c..379bd55e6 100644
--- a/tests/threads/tthreadheapviolation1.nim
+++ b/tests/threads/tthreadheapviolation1.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 11
   errormsg: "'horrible' is not GC-safe"
+  line: 11
   cmd: "nim $target --hints:on --threads:on $options $file"
 """
 
@@ -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
index 4a98e6c27..fcff94e78 100644
--- a/tests/threads/ttryrecv.nim
+++ b/tests/threads/ttryrecv.nim
@@ -1,17 +1,18 @@
 discard """
+  matrix: "--mm:refc"
   outputsub: "channel is empty"
 """
 
 # bug #1816
 
-from random import random
+from random import rand
 from os import sleep
 
 type PComm = ptr Channel[int]
 
 proc doAction(outC: PComm) {.thread.} =
-  for i in 0.. <5:
-    sleep(random(100))
+  for i in 0 ..< 5:
+    sleep(rand(50))
     send(outC[], i)
 
 var