better test program
This commit is contained in:
parent
69f2b67b5e
commit
1452edfbb9
1 changed files with 49 additions and 4 deletions
|
|
@ -1,21 +1,26 @@
|
||||||
# bug #2854
|
# bug #2854
|
||||||
|
|
||||||
|
# Test case for the compiler correctly detecting if a type used by a shared
|
||||||
|
# global is gcsafe.
|
||||||
|
|
||||||
import locks, threadpool, osproc
|
import locks, threadpool, osproc
|
||||||
|
|
||||||
const MAX_WORKERS = 10
|
const MAX_WORKERS = 50
|
||||||
|
|
||||||
type
|
type
|
||||||
Killer = object
|
Killer* = object
|
||||||
lock: Lock
|
lock: Lock
|
||||||
bailed {.guard: lock.}: bool
|
bailed {.guard: lock.}: bool
|
||||||
processes {.guard: lock.}: array[0..MAX_WORKERS-1, foreign ptr Process]
|
processes {.guard: lock.}: array[0..MAX_WORKERS-1, foreign ptr Process]
|
||||||
|
|
||||||
|
# Hold a lock for a statement.
|
||||||
template hold(lock: Lock, body: stmt) =
|
template hold(lock: Lock, body: stmt) =
|
||||||
lock.acquire
|
lock.acquire
|
||||||
defer: lock.release
|
defer: lock.release
|
||||||
{.locks: [lock].}:
|
{.locks: [lock].}:
|
||||||
body
|
body
|
||||||
|
|
||||||
|
# Return an initialized Killer.
|
||||||
proc initKiller*(): Killer =
|
proc initKiller*(): Killer =
|
||||||
initLock(result.lock)
|
initLock(result.lock)
|
||||||
result.lock.hold:
|
result.lock.hold:
|
||||||
|
|
@ -23,4 +28,44 @@ proc initKiller*(): Killer =
|
||||||
for i, _ in result.processes:
|
for i, _ in result.processes:
|
||||||
result.processes[i] = nil
|
result.processes[i] = nil
|
||||||
|
|
||||||
|
# Global Killer instance.
|
||||||
var killer = initKiller()
|
var killer = initKiller()
|
||||||
|
|
||||||
|
# remember that a process has been launched, killing it if we have bailed.
|
||||||
|
proc launched*(process: foreign 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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue