summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-01-18 13:41:55 +0100
committerAndreas Rumpf <rumpf_a@web.de>2017-01-18 13:41:55 +0100
commit61937974e2a7fcf3ff6427510f793c4b580f1b62 (patch)
tree3cc11bc32a1bf760a9715d62b1640a66dd08c78b /lib
parent2f08fdf6238baefca633ebbd2776ec366288e96d (diff)
downloadNim-61937974e2a7fcf3ff6427510f793c4b580f1b62.tar.gz
added system.onThreadCreation feature for safe thread local storage initializations
Diffstat (limited to 'lib')
-rw-r--r--lib/system/threads.nim31
1 files changed, 31 insertions, 0 deletions
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 3f8387459..dea6fff1c 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -307,6 +307,35 @@ type
                                        ## a pointer as a thread ID.
 {.deprecated: [TThread: Thread, TThreadId: ThreadId].}
 
+var
+  threadCreationHandlers: array[60, proc () {.nimcall, gcsafe.}]
+  countThreadCreationHandlers: int
+
+proc onThreadCreation*(handler: proc () {.nimcall, gcsafe.}) =
+  ## Registers a global handler that is called at thread creation.
+  ## This can be used to initialize thread local variables properly.
+  ## Note that the handler has to be .gcafe and so the typical usage
+  ## looks like:
+  ##
+  ## .. code-block:: nim
+  ##
+  ##  var
+  ##    someGlobal: string = "some string here"
+  ##    perThread {.threadvar.}: string
+  ##
+  ##  proc setPerThread() =
+  ##    {.gcsafe.}:
+  ##      deepCopy(perThread, someGlobal)
+  ##
+  ## **Note**: The registration is currently not threadsafe! Better
+  ## call ``onThreadCreation`` before any thread started its work!
+  threadCreationHandlers[countThreadCreationHandlers] = handler
+  inc countThreadCreationHandlers
+
+template beforeThreadRuns() =
+  for i in 0..countThreadCreationHandlers-1:
+    threadCreationHandlers[i]()
+
 when not defined(boehmgc) and not hasSharedHeap and not defined(gogc) and not defined(gcstack):
   proc deallocOsPages()
 
@@ -321,6 +350,7 @@ when defined(boehmgc):
 
   proc threadProcWrapDispatch[TArg](sb: pointer, thrd: pointer) {.noconv.} =
     boehmGC_register_my_thread(sb)
+    beforeThreadRuns()
     let thrd = cast[ptr Thread[TArg]](thrd)
     when TArg is void:
       thrd.dataFn()
@@ -329,6 +359,7 @@ when defined(boehmgc):
     boehmGC_unregister_my_thread()
 else:
   proc threadProcWrapDispatch[TArg](thrd: ptr Thread[TArg]) =
+    beforeThreadRuns()
     when TArg is void:
       thrd.dataFn()
     else: