很早前在折騰掛起LUA腳本支持時(shí),接觸到lua_yield這個(gè)函數(shù)。lua manual中給的解釋是:
This function should only be called as the return expression of a C function。
而這個(gè)函數(shù)一般是在一個(gè)注冊到LUA環(huán)境中的C函數(shù)里被調(diào)用。lua_CFunction要求的原型里
,函數(shù)的返回值必須返回要返回到LUA腳本中的值的個(gè)數(shù)。也就是說,在一個(gè)不需要掛起的
lua_CFunction實(shí)現(xiàn)里,也就是一個(gè)不需要return lua_yield(...的實(shí)現(xiàn)里,我應(yīng)該return
一個(gè)返回值個(gè)數(shù)。
但是為什么調(diào)用lua_yield就必須放在return表達(dá)式里?當(dāng)時(shí)很天真,沒去深究,反正發(fā)現(xiàn)
不按照lua manual里說的做就是不行。而且關(guān)鍵是,lua manual就不告訴你為什么。
最近突然就想到這個(gè)問題,決定去搞清楚這個(gè)問題。侯捷說了,源碼面前了無秘密。我甚至
在看代碼之前,還琢磨著LUA是不是操作了堆棧(系統(tǒng)堆棧)之類的東西。結(jié)果隨便跟了下
代碼真的讓我很汗顏。有時(shí)候人犯傻了真的是一個(gè)悲劇。諾簡單的一個(gè)問題會(huì)被人搞得很神
秘:
解釋執(zhí)行調(diào)用一個(gè)注冊進(jìn)LUA的lua_CFunction是在ldo.c里的luaD_precall函數(shù)里,有如下
代碼:

n = (*curr_func(L)->c.f)(L); /**//* do the actual call */
lua_lock(L);

if (n < 0) /**//* yielding? */
return PCRYIELD;

else
{
luaD_poscall(L, L->top - n);
return PCRC;
}
多的我就不說了,別人注釋寫得很清楚了,注冊進(jìn)去的lua_CFunction如果返回值小于0,這
個(gè)函數(shù)就向上層返回PCRYIELD,從名字就可看出是告訴上層需要YIELD。再找到lua_yield函
數(shù)的實(shí)現(xiàn),恰好該函數(shù)就返回-1。
要再往上層跟,會(huì)到lvm.c里luaV_execute函數(shù),看起來應(yīng)該就是虛擬機(jī)在解釋執(zhí)行指令:

case OP_CALL:
{
int b = GETARG_B(i);
int nresults = GETARG_C(i) - 1;

if (b != 0) L->top = ra+b; /**//* else previous instruction set top */
L->savedpc = pc;

switch (luaD_precall(L, ra, nresults))
{

case PCRLUA:
{
nexeccalls++;

goto reentry; /**//* restart luaV_execute over new Lua function */
}

case PCRC:
{

/**//* it was a C function (`precall' called it); adjust results */
if (nresults >= 0) L->top = L->ci->top;
base = L->base;
continue;