onThreadDestruction feature added to Nim's threading model
This commit is contained in:
parent
0ead17bf0e
commit
eb96eaa5c2
2 changed files with 38 additions and 12 deletions
|
|
@ -311,6 +311,9 @@ var
|
||||||
threadCreationHandlers: array[60, proc () {.nimcall, gcsafe.}]
|
threadCreationHandlers: array[60, proc () {.nimcall, gcsafe.}]
|
||||||
countThreadCreationHandlers: int
|
countThreadCreationHandlers: int
|
||||||
|
|
||||||
|
threadDestructionHandlers: array[60, proc () {.nimcall, gcsafe.}]
|
||||||
|
countThreadDestructionHandlers: int
|
||||||
|
|
||||||
proc onThreadCreation*(handler: proc () {.nimcall, gcsafe.}) =
|
proc onThreadCreation*(handler: proc () {.nimcall, gcsafe.}) =
|
||||||
## Registers a global handler that is called at thread creation.
|
## Registers a global handler that is called at thread creation.
|
||||||
## This can be used to initialize thread local variables properly.
|
## This can be used to initialize thread local variables properly.
|
||||||
|
|
@ -334,10 +337,22 @@ proc onThreadCreation*(handler: proc () {.nimcall, gcsafe.}) =
|
||||||
threadCreationHandlers[countThreadCreationHandlers] = handler
|
threadCreationHandlers[countThreadCreationHandlers] = handler
|
||||||
inc countThreadCreationHandlers
|
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.
|
||||||
|
threadDestructionHandlers[countThreadDestructionHandlers] = handler
|
||||||
|
inc countThreadDestructionHandlers
|
||||||
|
|
||||||
template beforeThreadRuns() =
|
template beforeThreadRuns() =
|
||||||
for i in 0..countThreadCreationHandlers-1:
|
for i in 0..countThreadCreationHandlers-1:
|
||||||
threadCreationHandlers[i]()
|
threadCreationHandlers[i]()
|
||||||
|
|
||||||
|
template afterThreadRuns() =
|
||||||
|
for i in 0..countThreadDestructionHandlers-1:
|
||||||
|
threadDestructionHandlers[i]()
|
||||||
|
|
||||||
proc runOnThreadCreationHandlers*() =
|
proc runOnThreadCreationHandlers*() =
|
||||||
## This runs every registered ``onThreadCreation`` handler and is usually
|
## This runs every registered ``onThreadCreation`` handler and is usually
|
||||||
## used to initialize thread local storage for the main thread. Since the
|
## used to initialize thread local storage for the main thread. Since the
|
||||||
|
|
@ -360,21 +375,27 @@ 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()
|
beforeThreadRuns()
|
||||||
|
try:
|
||||||
let thrd = cast[ptr Thread[TArg]](thrd)
|
let thrd = cast[ptr Thread[TArg]](thrd)
|
||||||
when TArg is void:
|
when TArg is void:
|
||||||
thrd.dataFn()
|
thrd.dataFn()
|
||||||
else:
|
else:
|
||||||
thrd.dataFn(thrd.data)
|
thrd.dataFn(thrd.data)
|
||||||
|
finally:
|
||||||
|
afterThreadRuns()
|
||||||
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()
|
beforeThreadRuns()
|
||||||
|
try:
|
||||||
when TArg is void:
|
when TArg is void:
|
||||||
thrd.dataFn()
|
thrd.dataFn()
|
||||||
else:
|
else:
|
||||||
var x: TArg
|
var x: TArg
|
||||||
deepCopy(x, thrd.data)
|
deepCopy(x, thrd.data)
|
||||||
thrd.dataFn(x)
|
thrd.dataFn(x)
|
||||||
|
finally:
|
||||||
|
afterThreadRuns()
|
||||||
|
|
||||||
proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
|
proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
|
||||||
when defined(boehmgc):
|
when defined(boehmgc):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''some string here'''
|
output: '''some string here
|
||||||
|
dying some string here'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -10,11 +11,15 @@ proc setPerThread() =
|
||||||
{.gcsafe.}:
|
{.gcsafe.}:
|
||||||
deepCopy(perThread, someGlobal)
|
deepCopy(perThread, someGlobal)
|
||||||
|
|
||||||
|
proc threadDied() {.gcsafe} =
|
||||||
|
echo "dying ", perThread
|
||||||
|
|
||||||
proc foo() {.thread.} =
|
proc foo() {.thread.} =
|
||||||
echo perThread
|
echo perThread
|
||||||
|
|
||||||
proc main =
|
proc main =
|
||||||
onThreadCreation setPerThread
|
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