summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-12-11 23:29:26 +0100
committerAraq <rumpf_a@web.de>2014-12-11 23:29:26 +0100
commit5a52e941b5a5e6fa92b76608dc8ed599821cd6c8 (patch)
treea37057f5321fc505dea093f86f27ada793787dfb
parent50e156db6ecfdd23b6c7d3a5fb3d93974dca2cd8 (diff)
downloadNim-5a52e941b5a5e6fa92b76608dc8ed599821cd6c8.tar.gz
added 'setupGcForForeignThread' for better C interop
-rw-r--r--lib/system/gc.nim14
-rw-r--r--lib/system/gc_ms.nim14
2 files changed, 28 insertions, 0 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index fe4b40903..e0db3fba4 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -292,6 +292,20 @@ proc initGC() =
     when useMarkForDebug or useBackupGc:
       init(gch.marked)
 
+var
+  localGcInitialized {.rtlThreadVar.}: bool
+
+proc setupForeignThreadGc*() =
+  ## call this if you registered a callback that will be run from a thread not
+  ## under your control. This has a cheap thread-local guard, so the GC for
+  ## this thread will only be initialized once per thread, no matter how often
+  ## it is called.
+  if not localGcInitialized:
+    localGcInitialized = true
+    var stackTop {.volatile.}: pointer
+    setStackBottom(addr(stackTop))
+    initGC()
+
 when useMarkForDebug or useBackupGc:
   type
     TGlobalMarkerProc = proc () {.nimcall, benign.}
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index 242ca1608..0eafd3255 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -168,6 +168,20 @@ proc initGC() =
       Init(gch.allocated)
       init(gch.marked)
 
+var
+  localGcInitialized {.rtlThreadVar.}: bool
+
+proc setupForeignThreadGc*() =
+  ## call this if you registered a callback that will be run from a thread not
+  ## under your control. This has a cheap thread-local guard, so the GC for
+  ## this thread will only be initialized once per thread, no matter how often
+  ## it is called.
+  if not localGcInitialized:
+    localGcInitialized = true
+    var stackTop {.volatile.}: pointer
+    setStackBottom(addr(stackTop))
+    initGC()
+
 proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.benign.} =
   var d = cast[ByteAddress](dest)
   case n.kind