tptr_to_ref.nim 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. # bug #2854
  2. # Test case for the compiler correctly detecting if a type used by a shared
  3. # global is gcsafe.
  4. import locks, threadpool, osproc
  5. const MAX_WORKERS = 50
  6. type
  7. Killer* = object
  8. lock: Lock
  9. bailed {.guard: lock.}: bool
  10. processes {.guard: lock.}: array[0..MAX_WORKERS-1, ptr Process]
  11. # Hold a lock for a statement.
  12. template hold(lock: Lock, body: untyped) =
  13. lock.acquire
  14. defer: lock.release
  15. {.locks: [lock].}:
  16. body
  17. # Return an initialized Killer.
  18. proc initKiller*(): Killer =
  19. initLock(result.lock)
  20. result.lock.hold:
  21. result.bailed = false
  22. for i, _ in result.processes:
  23. result.processes[i] = nil
  24. # Global Killer instance.
  25. var killer = initKiller()
  26. # remember that a process has been launched, killing it if we have bailed.
  27. proc launched*(process: ptr Process): int {.gcsafe.} =
  28. result = killer.processes.high + 1
  29. killer.lock.hold:
  30. if killer.bailed:
  31. process[].terminate()
  32. else:
  33. for i, _ in killer.processes:
  34. if killer.processes[i] == nil:
  35. killer.processes[i] = process
  36. result = i
  37. assert(result <= killer.processes.high)
  38. # A process has been finished with - remove the process from death row.
  39. # Return true if the process was still present, which will be the
  40. # case unless we have bailed.
  41. proc completed*(index: int): bool {.gcsafe.} =
  42. result = true
  43. if index <= killer.processes.high:
  44. killer.lock.hold:
  45. result = false
  46. if killer.processes[index] != nil:
  47. result = true
  48. killer.processes[index] = nil
  49. # Terminate all the processes killer knows about, doing nothing if
  50. # already bailed.
  51. proc bail(): bool {.gcsafe.} =
  52. killer.lock.hold:
  53. result = not killer.bailed
  54. if not killer.bailed:
  55. killer.bailed = true
  56. for i, process in killer.processes:
  57. if process != nil:
  58. process[].terminate
  59. killer.processes[i] = nil