lua_yield为什么就必须在return表达式中被调用

简介:

很早前在折腾挂起LUA脚本支持时,接触到lua_yield这个函数。lua manual中给的解释是:

This function should only be called as the return expression of a C function。

而这个函数一般是在一个注册到LUA环境中的C函数里被调用。lua_CFunction要求的原型里
,函数的返回值必须返回要返回到LUA脚本中的值的个数。也就是说,在一个不需要挂起的
lua_CFunction实现里,也就是一个不需要return lua_yield(...的实现里,我应该return
一个返回值个数。

但是为什么调用lua_yield就必须放在return表达式里?当时很天真,没去深究,反正发现
不按照lua manual里说的做就是不行。而且关键是,lua manual就不告诉你为什么。

最近突然就想到这个问题,决定去搞清楚这个问题。侯捷说了,源码面前了无秘密。我甚至
在看代码之前,还琢磨着LUA是不是操作了堆栈(系统堆栈)之类的东西。结果随便跟了下
代码真的让我很汗颜。有时候人犯傻了真的是一个悲剧。诺简单的一个问题会被人搞得很神
秘:

解释执行调用一个注册进LUA的lua_CFunction是在ldo.c里的luaD_precall函数里,有如下
代码:

    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;
    }

 

多的我就不说了,别人注释写得很清楚了,注册进去的lua_CFunction如果返回值小于0,这
个函数就向上层返回PCRYIELD,从名字就可看出是告诉上层需要YIELD。再找到lua_yield函
数的实现,恰好该函数就返回-1。

要再往上层跟,会到lvm.c里luaV_execute函数,看起来应该就是虚拟机在解释执行指令:

       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;

对于PCRYIELD返回值,直接忽略处理了。

目录
相关文章
|
C++ 索引
[Lua]Lua语言基础汇总(2) -- 表达式
算术操作符 Lua支持常规的算术操作符有:”+”(加法),”-”(减法),”*”(乘法),”/”(除法),”^”(指数),”%”(取模),一元的”-”(负号)。所有的这些操作符都用于实数。
991 0
|
6月前
|
存储 NoSQL Redis
Redis的Lua脚本有什么作用?
Redis Lua脚本用于减少网络开销、实现原子操作及扩展指令集。它能合并操作降低网络延迟,保证原子性,替代不支持回滚的事务。通过脚本,代码复用率提高,且可自定义指令,如实现分布式锁,增强Redis功能和灵活性。
254 1
|
5月前
|
消息中间件 NoSQL Java
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
229 0
|
1月前
|
缓存 分布式计算 NoSQL
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
31 2
|
2月前
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
3月前
|
存储 NoSQL Redis
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决
|
5月前
|
JSON 监控 数据格式
使用Lua代码扩展上网行为管理软件的脚本功能
本文介绍了如何使用Lua脚本增强上网行为管理,包括过滤URL、记录用户访问日志、控制带宽和自动提交监控数据到网站。Lua是一种轻量级语言,适合编写扩展脚本。文中提供多个示例代码,如URL过滤器、用户活动日志记录器和带宽控制器,帮助用户根据需求定制网络管理功能。通过这些示例,用户可以快速掌握Lua在上网行为管理中的应用。
176 4
|
5月前
|
NoSQL API Redis
使用Redis Lua脚本实现高级限流策略
使用Redis Lua脚本实现高级限流策略
203 0
下一篇
无影云桌面