foreign_thr.nim 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. discard """
  2. output: '''
  3. Hello from thread
  4. Hello from thread
  5. Hello from thread
  6. Hello from thread
  7. '''
  8. cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file"
  9. """
  10. # Copied from stdlib
  11. import strutils
  12. const
  13. StackGuardSize = 4096
  14. ThreadStackMask = 1024*256*sizeof(int)-1
  15. ThreadStackSize = ThreadStackMask+1 - StackGuardSize
  16. type ThreadFunc = proc() {.thread.}
  17. when defined(posix):
  18. import posix
  19. proc runInForeignThread(f: ThreadFunc) =
  20. proc wrapper(p: pointer): pointer {.noconv.} =
  21. let thr = cast[ThreadFunc](p)
  22. setupForeignThreadGc()
  23. thr()
  24. tearDownForeignThreadGc()
  25. setupForeignThreadGc()
  26. thr()
  27. tearDownForeignThreadGc()
  28. result = nil
  29. var attrs {.noinit.}: PthreadAttr
  30. doAssert pthread_attr_init(addr attrs) == 0
  31. doAssert pthread_attr_setstacksize(addr attrs, ThreadStackSize) == 0
  32. var tid: Pthread
  33. doAssert pthread_create(addr tid, addr attrs, wrapper, f) == 0
  34. doAssert pthread_join(tid, nil) == 0
  35. elif defined(windows):
  36. import winlean
  37. type
  38. WinThreadProc = proc (x: pointer): int32 {.stdcall.}
  39. proc createThread(lpThreadAttributes: pointer, dwStackSize: DWORD,
  40. lpStartAddress: WinThreadProc,
  41. lpParameter: pointer,
  42. dwCreationFlags: DWORD,
  43. lpThreadId: var DWORD): Handle {.
  44. stdcall, dynlib: "kernel32", importc: "CreateThread".}
  45. proc wrapper(p: pointer): int32 {.stdcall.} =
  46. let thr = cast[ThreadFunc](p)
  47. setupForeignThreadGc()
  48. thr()
  49. tearDownForeignThreadGc()
  50. setupForeignThreadGc()
  51. thr()
  52. tearDownForeignThreadGc()
  53. result = 0'i32
  54. proc runInForeignThread(f: ThreadFunc) =
  55. var dummyThreadId: DWORD
  56. var h = createThread(nil, ThreadStackSize.int32, wrapper.WinThreadProc, cast[pointer](f), 0, dummyThreadId)
  57. doAssert h != 0.Handle
  58. doAssert waitForSingleObject(h, -1'i32) == 0.DWORD
  59. else:
  60. {.fatal: "Unknown system".}
  61. proc runInNativeThread(f: ThreadFunc) =
  62. proc wrapper(f: ThreadFunc) {.thread.} =
  63. # These operations must be NOP
  64. setupForeignThreadGc()
  65. tearDownForeignThreadGc()
  66. f()
  67. f()
  68. var thr: Thread[ThreadFunc]
  69. createThread(thr, wrapper, f)
  70. joinThread(thr)
  71. proc f {.thread.} =
  72. var msg = "Hello " & "from thread"
  73. echo msg
  74. runInForeignThread(f)
  75. runInNativeThread(f)