🚀 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,
|
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`.
|
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.
|
`op_callb` will do `top[0]=resume()`, so the value does not change.
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
|
|
|
@ -526,7 +526,7 @@ __接下来我们解释这个协程的运行原理:__
|
||||||
|
|
||||||
接着我们调用`resume`,这个函数会替换操作数栈。我们会看到,协程的操作数栈上已经保存了一些数据,但是我们首次进入协程执行时,这个操作数栈的栈顶将会是`vm_ret`,并且返回的`pc`值是`0`。
|
接着我们调用`resume`,这个函数会替换操作数栈。我们会看到,协程的操作数栈上已经保存了一些数据,但是我们首次进入协程执行时,这个操作数栈的栈顶将会是`vm_ret`,并且返回的`pc`值是`0`。
|
||||||
|
|
||||||
为了保证栈顶的数据不会被破坏,`resume`会返回`gc.top[0]`。`op_callb`将会执行`top[0]=resume()`,所以栈顶的数据虽然被覆盖了一次,但是实际上还是原来的数据。
|
首次调用时,为了保证栈顶的数据不会被破坏,`resume`会返回`gc.top[0]`。`op_callb`将会执行`top[0]=resume()`,所以栈顶的数据虽然被覆盖了一次,但是实际上还是原来的数据。
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
+----------------------+(协程操作数栈)
|
+----------------------+(协程操作数栈)
|
||||||
|
|
|
@ -1165,9 +1165,21 @@ var builtin_coresume(var* local,gc& ngc) {
|
||||||
|
|
||||||
// fetch coroutine's stack top and return
|
// fetch coroutine's stack top and return
|
||||||
// so the coroutine's stack top in fact is not changed
|
// so the coroutine's stack top in fact is not changed
|
||||||
|
if (ngc.top[0].type==vm_ret) {
|
||||||
|
// when first calling this coroutine, the stack top must be vm_ret
|
||||||
return ngc.top[0];
|
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) {
|
var builtin_coyield(var* local,gc& ngc) {
|
||||||
if (!ngc.cort) {
|
if (!ngc.cort) {
|
||||||
return nas_err("coroutine::yield","no coroutine is running");
|
return nas_err("coroutine::yield","no coroutine is running");
|
||||||
|
|
|
@ -624,6 +624,7 @@ void vm::o_feach() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm::o_callg() {
|
void vm::o_callg() {
|
||||||
|
// get main stack directly
|
||||||
(++top)[0]=stack[imm[pc]];
|
(++top)[0]=stack[imm[pc]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -508,7 +508,7 @@ var compile=func(code,filename="<compile>"){
|
||||||
|
|
||||||
var coroutine={
|
var coroutine={
|
||||||
create: func(function) {return __cocreate;},
|
create: func(function) {return __cocreate;},
|
||||||
resume: func(co) {return __coresume;},
|
resume: func(co,args...) {return __coresume;},
|
||||||
yield: func(args...) {return __coyield; },
|
yield: func(args...) {return __coyield; },
|
||||||
status: func(co) {return __costatus;},
|
status: func(co) {return __costatus;},
|
||||||
running:func() {return __corun; }
|
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
|
# test crash in coroutines
|
||||||
var co=coroutine.create(func{
|
var co=coroutine.create(func{
|
||||||
var b=func(){b()}
|
var b=func(){b()}
|
||||||
|
|
Loading…
Reference in New Issue