summary refs log tree commit diff stats
path: root/lib/std/exitprocs.nim
blob: b2811735cc6094407867447d4779ce5d4c7ca78d (plain) (blame)
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
#
#
#            Nim's Runtime Library
#        (c) Copyright 2020 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

import locks

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: seq[Fun]

initLock(gFunsLock)

when defined(js):
  proc addAtExit(quitProc: proc() {.noconv.}) =
    when defined(nodejs):
      asm """
        process.on('exit', `quitProc`);
      """
    elif defined(js):
      asm """
        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()

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)