123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- # bug #2854
- # Test case for the compiler correctly detecting if a type used by a shared
- # global is gcsafe.
- import locks, threadpool, osproc
- const MAX_WORKERS = 50
- type
- Killer* = object
- lock: Lock
- bailed {.guard: lock.}: bool
- processes {.guard: lock.}: array[0..MAX_WORKERS-1, ptr Process]
- # Hold a lock for a statement.
- template hold(lock: Lock, body: untyped) =
- lock.acquire
- defer: lock.release
- {.locks: [lock].}:
- body
- # Return an initialized Killer.
- proc initKiller*(): Killer =
- initLock(result.lock)
- result.lock.hold:
- result.bailed = false
- for i, _ in result.processes:
- result.processes[i] = nil
- # Global Killer instance.
- var killer = initKiller()
- # remember that a process has been launched, killing it if we have bailed.
- proc launched*(process: ptr Process): int {.gcsafe.} =
- result = killer.processes.high + 1
- killer.lock.hold:
- if killer.bailed:
- process[].terminate()
- else:
- for i, _ in killer.processes:
- if killer.processes[i] == nil:
- killer.processes[i] = process
- result = i
- assert(result <= killer.processes.high)
- # A process has been finished with - remove the process from death row.
- # Return true if the process was still present, which will be the
- # case unless we have bailed.
- proc completed*(index: int): bool {.gcsafe.} =
- result = true
- if index <= killer.processes.high:
- killer.lock.hold:
- result = false
- if killer.processes[index] != nil:
- result = true
- killer.processes[index] = nil
- # Terminate all the processes killer knows about, doing nothing if
- # already bailed.
- proc bail(): bool {.gcsafe.} =
- killer.lock.hold:
- result = not killer.bailed
- if not killer.bailed:
- killer.bailed = true
- for i, process in killer.processes:
- if process != nil:
- process[].terminate
- killer.processes[i] = nil
|