diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-01-18 13:41:55 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-01-18 13:41:55 +0100 |
commit | 61937974e2a7fcf3ff6427510f793c4b580f1b62 (patch) | |
tree | 3cc11bc32a1bf760a9715d62b1640a66dd08c78b /lib | |
parent | 2f08fdf6238baefca633ebbd2776ec366288e96d (diff) | |
download | Nim-61937974e2a7fcf3ff6427510f793c4b580f1b62.tar.gz |
added system.onThreadCreation feature for safe thread local storage initializations
Diffstat (limited to 'lib')
-rw-r--r-- | lib/system/threads.nim | 31 |
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: |