🚀 coroutine.resume can pass arguments
This commit is contained in:
parent
e6e89039b8
commit
48611c50f7
|
@ -587,7 +587,7 @@ Then we call `resume`, this function will change stack.
|
|||
As we can see, coroutine stack already has some values on it,
|
||||
but if we first enter it, the stack top will be `vm_ret`, and the return `pc` is `0`.
|
||||
|
||||
So for safe running, `resume` will return `gc.top[0]`.
|
||||
So for safe running, when first calling the coroutine, `resume` will return `gc.top[0]`.
|
||||
`op_callb` will do `top[0]=resume()`, so the value does not change.
|
||||
|
||||
```C++
|
||||
|
|
|
@ -526,7 +526,7 @@ __接下来我们解释这个协程的运行原理:__
|
|||
|
||||
接着我们调用`resume`,这个函数会替换操作数栈。我们会看到,协程的操作数栈上已经保存了一些数据,但是我们首次进入协程执行时,这个操作数栈的栈顶将会是`vm_ret`,并且返回的`pc`值是`0`。
|
||||
|
||||
为了保证栈顶的数据不会被破坏,`resume`会返回`gc.top[0]`。`op_callb`将会执行`top[0]=resume()`,所以栈顶的数据虽然被覆盖了一次,但是实际上还是原来的数据。
|
||||
首次调用时,为了保证栈顶的数据不会被破坏,`resume`会返回`gc.top[0]`。`op_callb`将会执行`top[0]=resume()`,所以栈顶的数据虽然被覆盖了一次,但是实际上还是原来的数据。
|
||||
|
||||
```C++
|
||||
+----------------------+(协程操作数栈)
|
||||
|
|
|
@ -1165,7 +1165,19 @@ var builtin_coresume(var* local,gc& ngc) {
|
|||
|
||||
// fetch coroutine's stack top and return
|
||||
// so the coroutine's stack top in fact is not changed
|
||||
return ngc.top[0];
|
||||
if (ngc.top[0].type==vm_ret) {
|
||||
// when first calling this coroutine, the stack top must be vm_ret
|
||||
return ngc.top[0];
|
||||
}
|
||||
|
||||
// after first calling the coroutine, each time coroutine.yield triggered
|
||||
// a new space will be reserved on stack with value nil
|
||||
// so we could fill this place with args
|
||||
|
||||
// the coroutine seems like coroutine.yield returns the value
|
||||
// but in fact coroutine.yield stop the coroutine
|
||||
// until main context calls the coroutine.resume
|
||||
return local[2];
|
||||
}
|
||||
|
||||
var builtin_coyield(var* local,gc& ngc) {
|
||||
|
|
|
@ -715,7 +715,7 @@ void gc::ctxchg(nas_co& ctx) {
|
|||
|
||||
void gc::ctxreserve() {
|
||||
// pc=0 means this coroutine is finished
|
||||
cort->status=pc?nas_co::suspended:nas_co::dead;
|
||||
cort->status=pc? nas_co::suspended:nas_co::dead;
|
||||
cort->pc=pc;
|
||||
cort->localr=localr;
|
||||
cort->memr=memr;
|
||||
|
|
|
@ -624,6 +624,7 @@ void vm::o_feach() {
|
|||
}
|
||||
|
||||
void vm::o_callg() {
|
||||
// get main stack directly
|
||||
(++top)[0]=stack[imm[pc]];
|
||||
}
|
||||
|
||||
|
|
10
stl/lib.nas
10
stl/lib.nas
|
@ -507,9 +507,9 @@ var compile=func(code,filename="<compile>"){
|
|||
}
|
||||
|
||||
var coroutine={
|
||||
create: func(function){return __cocreate;},
|
||||
resume: func(co) {return __coresume;},
|
||||
yield: func(args...) {return __coyield; },
|
||||
status: func(co) {return __costatus;},
|
||||
running:func() {return __corun; }
|
||||
create: func(function) {return __cocreate;},
|
||||
resume: func(co,args...) {return __coresume;},
|
||||
yield: func(args...) {return __coyield; },
|
||||
status: func(co) {return __costatus;},
|
||||
running:func() {return __corun; }
|
||||
};
|
||||
|
|
|
@ -40,6 +40,20 @@ func(){
|
|||
}
|
||||
}();
|
||||
|
||||
# test coroutine.resume passing arguments to coroutine
|
||||
func{
|
||||
var co=coroutine.create(func(){
|
||||
var (a,b)=coroutine.yield(a+b);
|
||||
println("coroutine.yield get ",a," ",b);
|
||||
(a,b)=coroutine.yield(a+b);
|
||||
println("coroutine.yield get ",a," ",b);
|
||||
return "end";
|
||||
});
|
||||
|
||||
for(var i=0;i<5;i+=1)
|
||||
println("coroutine.resume get ",coroutine.resume(co,i,i+1));
|
||||
}();
|
||||
|
||||
# test crash in coroutines
|
||||
var co=coroutine.create(func{
|
||||
var b=func(){b()}
|
||||
|
|
Loading…
Reference in New Issue