1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
#
#
# Nim's Runtime Library
# (c) Copyright 2020 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module allows adding hooks to program exit.
import std/locks
when defined(js) and not defined(nodejs):
import std/assertions
type
FunKind = enum kClosure, kNoconv # extend as needed
Fun = object
case kind: FunKind
of kClosure: fun1: proc () {.closure.}
of kNoconv: fun2: proc () {.noconv.}
var
gFunsLock: Lock
gFuns {.cursor.}: seq[Fun] #Intentionally use the cursor to break up the lifetime trace and make it compatible with JS.
initLock(gFunsLock)
when defined(js):
proc addAtExit(quitProc: proc() {.noconv.}) =
when defined(nodejs):
{.emit: """
process.on('exit', `quitProc`);
""".}
elif defined(js):
{.emit: """
window.onbeforeunload = `quitProc`;
""".}
else:
proc addAtExit(quitProc: proc() {.noconv.}) {.
importc: "atexit", header: "<stdlib.h>".}
proc callClosures() {.noconv.} =
withLock gFunsLock:
for i in countdown(gFuns.len-1, 0):
let fun = gFuns[i]
case fun.kind
of kClosure: fun.fun1()
of kNoconv: fun.fun2()
gFuns.setLen(0)
template fun() =
if gFuns.len == 0:
addAtExit(callClosures)
proc addExitProc*(cl: proc () {.closure.}) =
## Adds/registers a quit procedure. Each call to `addExitProc` registers
## another quit procedure. They are executed on a last-in, first-out basis.
# Support for `addExitProc` is done by Ansi C's facilities here.
# In case of an unhandled exception the exit handlers should
# not be called explicitly! The user may decide to do this manually though.
withLock gFunsLock:
fun()
gFuns.add Fun(kind: kClosure, fun1: cl)
proc addExitProc*(cl: proc() {.noconv.}) =
## overload for `noconv` procs.
withLock gFunsLock:
fun()
gFuns.add Fun(kind: kNoconv, fun2: cl)
when not defined(nimscript) and (not defined(js) or defined(nodejs)):
proc getProgramResult*(): int =
when defined(js) and defined(nodejs):
{.emit: """
`result` = process.exitCode;
""".}
else:
result = programResult
proc setProgramResult*(a: int) =
when defined(js) and defined(nodejs):
{.emit: """
process.exitCode = `a`;
""".}
else:
programResult = a
|