* done * Apply suggestions from code review * fixup Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
This commit is contained in:
parent
57d5c1465a
commit
dfe6797023
3 changed files with 53 additions and 33 deletions
|
|
@ -32,6 +32,10 @@ import lists
|
||||||
include system/timers
|
include system/timers
|
||||||
|
|
||||||
const defaultStackSize = 512 * 1024
|
const defaultStackSize = 512 * 1024
|
||||||
|
const useOrcArc = defined(gcArc) or defined(gcOrc)
|
||||||
|
|
||||||
|
when useOrcArc:
|
||||||
|
proc nimGC_setStackBottom*(theStackBottom: pointer) = discard
|
||||||
|
|
||||||
proc GC_addStack(bottom: pointer) {.cdecl, importc.}
|
proc GC_addStack(bottom: pointer) {.cdecl, importc.}
|
||||||
proc GC_removeStack(bottom: pointer) {.cdecl, importc.}
|
proc GC_removeStack(bottom: pointer) {.cdecl, importc.}
|
||||||
|
|
@ -59,7 +63,7 @@ else:
|
||||||
const coroBackend = CORO_BACKEND_UCONTEXT
|
const coroBackend = CORO_BACKEND_UCONTEXT
|
||||||
|
|
||||||
when coroBackend == CORO_BACKEND_FIBERS:
|
when coroBackend == CORO_BACKEND_FIBERS:
|
||||||
import windows.winlean
|
import windows/winlean
|
||||||
type
|
type
|
||||||
Context = pointer
|
Context = pointer
|
||||||
|
|
||||||
|
|
@ -185,7 +189,8 @@ proc initialize() =
|
||||||
ctx.coroutines = initDoublyLinkedList[CoroutinePtr]()
|
ctx.coroutines = initDoublyLinkedList[CoroutinePtr]()
|
||||||
ctx.loop = Coroutine()
|
ctx.loop = Coroutine()
|
||||||
ctx.loop.state = CORO_EXECUTING
|
ctx.loop.state = CORO_EXECUTING
|
||||||
ctx.ncbottom = GC_getActiveStack()
|
when not useOrcArc:
|
||||||
|
ctx.ncbottom = GC_getActiveStack()
|
||||||
when coroBackend == CORO_BACKEND_FIBERS:
|
when coroBackend == CORO_BACKEND_FIBERS:
|
||||||
ctx.loop.execContext = ConvertThreadToFiberEx(nil, FIBER_FLAG_FLOAT_SWITCH)
|
ctx.loop.execContext = ConvertThreadToFiberEx(nil, FIBER_FLAG_FLOAT_SWITCH)
|
||||||
|
|
||||||
|
|
@ -195,7 +200,8 @@ proc switchTo(current, to: CoroutinePtr) =
|
||||||
## Switches execution from `current` into `to` context.
|
## Switches execution from `current` into `to` context.
|
||||||
to.lastRun = getTicks()
|
to.lastRun = getTicks()
|
||||||
# Update position of current stack so gc invoked from another stack knows how much to scan.
|
# Update position of current stack so gc invoked from another stack knows how much to scan.
|
||||||
GC_setActiveStack(current.stack.bottom)
|
when not useOrcArc:
|
||||||
|
GC_setActiveStack(current.stack.bottom)
|
||||||
nimGC_setStackBottom(current.stack.bottom)
|
nimGC_setStackBottom(current.stack.bottom)
|
||||||
var frame = getFrameState()
|
var frame = getFrameState()
|
||||||
block:
|
block:
|
||||||
|
|
@ -218,7 +224,8 @@ proc switchTo(current, to: CoroutinePtr) =
|
||||||
{.error: "Invalid coroutine backend set.".}
|
{.error: "Invalid coroutine backend set.".}
|
||||||
# Execution was just resumed. Restore frame information and set active stack.
|
# Execution was just resumed. Restore frame information and set active stack.
|
||||||
setFrameState(frame)
|
setFrameState(frame)
|
||||||
GC_setActiveStack(current.stack.bottom)
|
when not useOrcArc:
|
||||||
|
GC_setActiveStack(current.stack.bottom)
|
||||||
nimGC_setStackBottom(ctx.ncbottom)
|
nimGC_setStackBottom(ctx.ncbottom)
|
||||||
|
|
||||||
proc suspend*(sleepTime: float = 0) =
|
proc suspend*(sleepTime: float = 0) =
|
||||||
|
|
@ -241,9 +248,10 @@ proc runCurrentTask() =
|
||||||
# have to set active stack here as well. GC_removeStack() has to be called in main loop
|
# have to set active stack here as well. GC_removeStack() has to be called in main loop
|
||||||
# because we still need stack available in final suspend(0) call from which we will not
|
# because we still need stack available in final suspend(0) call from which we will not
|
||||||
# return.
|
# return.
|
||||||
GC_addStack(sp)
|
when not useOrcArc:
|
||||||
# Activate current stack because we are executing in a new coroutine.
|
GC_addStack(sp)
|
||||||
GC_setActiveStack(sp)
|
# Activate current stack because we are executing in a new coroutine.
|
||||||
|
GC_setActiveStack(sp)
|
||||||
current.state = CORO_EXECUTING
|
current.state = CORO_EXECUTING
|
||||||
try:
|
try:
|
||||||
current.fn() # Start coroutine execution
|
current.fn() # Start coroutine execution
|
||||||
|
|
@ -312,7 +320,8 @@ proc run*() =
|
||||||
next = ctx.current.next
|
next = ctx.current.next
|
||||||
current.reference.coro = nil
|
current.reference.coro = nil
|
||||||
ctx.coroutines.remove(ctx.current)
|
ctx.coroutines.remove(ctx.current)
|
||||||
GC_removeStack(current.stack.bottom)
|
when not useOrcArc:
|
||||||
|
GC_removeStack(current.stack.bottom)
|
||||||
when coroBackend == CORO_BACKEND_FIBERS:
|
when coroBackend == CORO_BACKEND_FIBERS:
|
||||||
DeleteFiber(current.execContext)
|
DeleteFiber(current.execContext)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
discard """
|
discard """
|
||||||
targets: "c"
|
matrix: "--gc:refc; --gc:arc; --gc:orc"
|
||||||
|
target: "c"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import coro
|
when compileOption("gc", "refc") or not defined(openbsd):
|
||||||
|
# xxx openbsd gave: stdlib_coro.nim.c:406:22: error: array type 'jmp_buf' (aka 'long [11]') is not assignable (*dest).execContext = src.execContext;
|
||||||
|
import coro
|
||||||
|
|
||||||
var maxOccupiedMemory = 0
|
var maxOccupiedMemory = 0
|
||||||
|
|
||||||
proc testGC() =
|
proc testGC() =
|
||||||
var numbers = newSeq[int](100)
|
var numbers = newSeq[int](100)
|
||||||
maxOccupiedMemory = max(maxOccupiedMemory, getOccupiedMem())
|
maxOccupiedMemory = max(maxOccupiedMemory, getOccupiedMem())
|
||||||
suspend(0)
|
suspend(0)
|
||||||
|
|
||||||
start(testGC)
|
start(testGC)
|
||||||
start(testGC)
|
start(testGC)
|
||||||
run()
|
run()
|
||||||
|
|
||||||
GC_fullCollect()
|
GC_fullCollect()
|
||||||
doAssert(getOccupiedMem() < maxOccupiedMemory, "GC did not free any memory allocated in coroutines")
|
doAssert(getOccupiedMem() < maxOccupiedMemory, "GC did not free any memory allocated in coroutines")
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,28 @@
|
||||||
discard """
|
discard """
|
||||||
output: "Exit 1\nExit 2"
|
output: "Exit 1\nExit 2"
|
||||||
targets: "c"
|
matrix: "--gc:refc; --gc:arc; --gc:orc"
|
||||||
|
target: "c"
|
||||||
"""
|
"""
|
||||||
import coro
|
|
||||||
|
|
||||||
var coro1: CoroutineRef
|
when compileOption("gc", "refc") or not defined(openbsd):
|
||||||
|
# xxx openbsd failed, see tgc.nim
|
||||||
|
import coro
|
||||||
|
|
||||||
proc testCoroutine1() =
|
var coro1: CoroutineRef
|
||||||
for i in 0..<10:
|
|
||||||
suspend(0)
|
proc testCoroutine1() =
|
||||||
|
for i in 0..<10:
|
||||||
|
suspend(0)
|
||||||
|
echo "Exit 1"
|
||||||
|
|
||||||
|
proc testCoroutine2() =
|
||||||
|
coro1.wait()
|
||||||
|
echo "Exit 2"
|
||||||
|
|
||||||
|
coro1 = coro.start(testCoroutine1)
|
||||||
|
coro.start(testCoroutine2)
|
||||||
|
run()
|
||||||
|
else:
|
||||||
|
# workaround
|
||||||
echo "Exit 1"
|
echo "Exit 1"
|
||||||
|
|
||||||
proc testCoroutine2() =
|
|
||||||
coro1.wait()
|
|
||||||
echo "Exit 2"
|
echo "Exit 2"
|
||||||
|
|
||||||
coro1 = coro.start(testCoroutine1)
|
|
||||||
coro.start(testCoroutine2)
|
|
||||||
run()
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue