removed onThreadCreation; onThreadDestruction is now thread local
This commit is contained in:
parent
df4954fac6
commit
4f062c3be0
3 changed files with 14 additions and 57 deletions
|
|
@ -62,8 +62,6 @@ be used:
|
||||||
{.gcsafe.}:
|
{.gcsafe.}:
|
||||||
deepCopy(perThread, someGlobal)
|
deepCopy(perThread, someGlobal)
|
||||||
|
|
||||||
onThreadCreation(setPerThread)
|
|
||||||
|
|
||||||
|
|
||||||
Future directions:
|
Future directions:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -355,58 +355,22 @@ type
|
||||||
{.deprecated: [TThread: Thread, TThreadId: ThreadId].}
|
{.deprecated: [TThread: Thread, TThreadId: ThreadId].}
|
||||||
|
|
||||||
var
|
var
|
||||||
threadCreationHandlers: array[60, proc () {.nimcall, gcsafe.}]
|
threadDestructionHandlers {.rtlThreadVar.}: seq[proc () {.closure, gcsafe.}]
|
||||||
countThreadCreationHandlers: int
|
|
||||||
|
|
||||||
threadDestructionHandlers: array[60, proc () {.nimcall, gcsafe.}]
|
proc onThreadDestruction*(handler: proc () {.closure, gcsafe.}) =
|
||||||
countThreadDestructionHandlers: int
|
## Registers a *thread local* handler that is called at the thread's
|
||||||
|
## destruction.
|
||||||
proc onThreadCreation*(handler: proc () {.nimcall, gcsafe.}) =
|
## A thread is destructed when the ``.thread`` proc returns
|
||||||
## Registers a global handler that is called at thread creation.
|
## normally or when it raises an exception. Note that unhandled exceptions
|
||||||
## 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)
|
|
||||||
##
|
|
||||||
## onThreadCreation(setPerThread)
|
|
||||||
##
|
|
||||||
## **Note**: The registration is currently not threadsafe! Better
|
|
||||||
## call ``onThreadCreation`` before any thread started its work!
|
|
||||||
threadCreationHandlers[countThreadCreationHandlers] = handler
|
|
||||||
inc countThreadCreationHandlers
|
|
||||||
|
|
||||||
proc onThreadDestruction*(handler: proc () {.nimcall, gcsafe.}) =
|
|
||||||
## Registers a global handler that is called at thread destruction.
|
|
||||||
## Threads are destructed when the ``.thread`` proc returns
|
|
||||||
## normally or raises an exception. Note that unhandled exceptions
|
|
||||||
## in a thread nevertheless cause the whole process to die.
|
## in a thread nevertheless cause the whole process to die.
|
||||||
threadDestructionHandlers[countThreadDestructionHandlers] = handler
|
if threadDestructionHandlers.isNil:
|
||||||
inc countThreadDestructionHandlers
|
threadDestructionHandlers = @[]
|
||||||
|
threadDestructionHandlers.add handler
|
||||||
template beforeThreadRuns() =
|
|
||||||
for i in 0..countThreadCreationHandlers-1:
|
|
||||||
threadCreationHandlers[i]()
|
|
||||||
|
|
||||||
template afterThreadRuns() =
|
template afterThreadRuns() =
|
||||||
for i in countdown(countThreadDestructionHandlers-1, 0):
|
for i in countdown(threadDestructionHandlers.len-1, 0):
|
||||||
threadDestructionHandlers[i]()
|
threadDestructionHandlers[i]()
|
||||||
|
|
||||||
proc runOnThreadCreationHandlers*() =
|
|
||||||
## This runs every registered ``onThreadCreation`` handler and is usually
|
|
||||||
## used to initialize thread local storage for the main thread. Since the
|
|
||||||
## main thread is **not** created via ``createThread`` it doesn't run the
|
|
||||||
## handlers automatically.
|
|
||||||
beforeThreadRuns()
|
|
||||||
|
|
||||||
when not defined(boehmgc) and not hasSharedHeap and not defined(gogc) and not defined(gcstack):
|
when not defined(boehmgc) and not hasSharedHeap and not defined(gogc) and not defined(gcstack):
|
||||||
proc deallocOsPages()
|
proc deallocOsPages()
|
||||||
|
|
||||||
|
|
@ -421,7 +385,6 @@ when defined(boehmgc):
|
||||||
|
|
||||||
proc threadProcWrapDispatch[TArg](sb: pointer, thrd: pointer) {.noconv.} =
|
proc threadProcWrapDispatch[TArg](sb: pointer, thrd: pointer) {.noconv.} =
|
||||||
boehmGC_register_my_thread(sb)
|
boehmGC_register_my_thread(sb)
|
||||||
beforeThreadRuns()
|
|
||||||
try:
|
try:
|
||||||
let thrd = cast[ptr Thread[TArg]](thrd)
|
let thrd = cast[ptr Thread[TArg]](thrd)
|
||||||
when TArg is void:
|
when TArg is void:
|
||||||
|
|
@ -433,7 +396,6 @@ when defined(boehmgc):
|
||||||
boehmGC_unregister_my_thread()
|
boehmGC_unregister_my_thread()
|
||||||
else:
|
else:
|
||||||
proc threadProcWrapDispatch[TArg](thrd: ptr Thread[TArg]) =
|
proc threadProcWrapDispatch[TArg](thrd: ptr Thread[TArg]) =
|
||||||
beforeThreadRuns()
|
|
||||||
try:
|
try:
|
||||||
when TArg is void:
|
when TArg is void:
|
||||||
thrd.dataFn()
|
thrd.dataFn()
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,16 @@ var
|
||||||
someGlobal: string = "some string here"
|
someGlobal: string = "some string here"
|
||||||
perThread {.threadvar.}: string
|
perThread {.threadvar.}: string
|
||||||
|
|
||||||
proc setPerThread() =
|
proc threadDied() {.gcsafe.} =
|
||||||
{.gcsafe.}:
|
|
||||||
deepCopy(perThread, someGlobal)
|
|
||||||
|
|
||||||
proc threadDied() {.gcsafe} =
|
|
||||||
echo "dying ", perThread
|
echo "dying ", perThread
|
||||||
|
|
||||||
proc foo() {.thread.} =
|
proc foo() {.thread.} =
|
||||||
|
onThreadDestruction threadDied
|
||||||
|
{.gcsafe.}:
|
||||||
|
deepCopy(perThread, someGlobal)
|
||||||
echo perThread
|
echo perThread
|
||||||
|
|
||||||
proc main =
|
proc main =
|
||||||
onThreadCreation setPerThread
|
|
||||||
onThreadDestruction threadDied
|
|
||||||
var t: Thread[void]
|
var t: Thread[void]
|
||||||
createThread[void](t, foo)
|
createThread[void](t, foo)
|
||||||
t.joinThread()
|
t.joinThread()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue