首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用fiber.yield()和fiber.testcancel()的Tarantool纤程行为

使用fiber.yield()和fiber.testcancel()的Tarantool纤程行为
EN

Stack Overflow用户
提问于 2020-06-08 20:47:37
回答 1查看 69关注 0票数 1

在构建基于纤程的Tarantool应用程序时,我遇到了意外的行为。

代码的简单复制器如下所示:

代码语言:javascript
复制
local log = require('log')
local fiber = require('fiber')

box.cfg{}

local func = function()
    for i = 1, 100000 do
        if pcall(fiber.testcancel) ~= true then
            return 1
        end

        fiber.yield()
    end

    return 0
end

local wrapfunc = function()
    local ok, resp = pcall(func)
    log.info(ok)
    log.info(resp)
end

for _ = 1, 100 do
    local myfiber = fiber.create(wrapfunc)
    fiber.sleep(0.02)
    fiber.kill(myfiber)
end

并打印到日志false, fiber is cancelled。此外,如果我使用下面的func

代码语言:javascript
复制
local func = function()
    for i = 1, 100000 do
        if pcall(fiber.testcancel) ~= true then
            return 1
        end

        pcall(fiber.yield)
    end

    return 0
end

它打印到日志true, 1,如果我使用

代码语言:javascript
复制
local func = function()
    for i = 1, 100000 do
        if pcall(fiber.testcancel) ~= true then
            return 1
        end

        if pcall(fiber.yield) ~= true then
            return 2
        end
    end

    return 0
end

它打印到日志true, 2

我期望在运行myfiber之后,如果控制返回到外部纤程并调用fiber.kill(myfiber),那么下一次控制返回到取消的myfiber时,我们将处于循环迭代的末尾,下一次迭代代码将成功返回1。然而,func的工作以抛出错误fiber is cancelled结束,而不是返回。那么,产生纤维的真实生命周期是如何工作的呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-08 22:07:03

实际上,这里没有意外的行为。我相信它主要是文档问题。让我解释一下。我对你的例子做了一些简化:

代码语言:javascript
复制
#!/usr/bin/env tarantool

local fiber = require('fiber')

local f1 = function() fiber.yield() end
local f2 = function() pcall(fiber.yield) end

local func = function(fn)
    fn()
    if not pcall(fiber.testcancel) then
        return 'fiber.testcancel() failed'
    end
end

local fiber1 = fiber.create(function() print(pcall(func, f1)) end)
fiber.kill(fiber1)
local fiber2 = fiber.create(function() print(pcall(func, f2)) end)
fiber.kill(fiber2)

输出将为:

代码语言:javascript
复制
false   fiber is cancelled
true    fiber.testcancel() failed

当您调用fiber.kill时,fiber.yield()fiber.sleep()只会引发一个错误,因此您的光纤无法到达fiber.testcancel,因此就会死掉。当您执行pcall(fiber.yield)时,您基本上抑制了此错误并继续执行。然后,fiber.testcancel检查其光纤状态并重新引发异常。但这是一个愚蠢的例子。

现在,有了更大的代码块,当涉及到许多函数调用时,您通常希望在yield期间捕获这些错误,做一些终结工作,并调用fiber.testcancel()来向上提升错误(想象一下在大型堆栈跟踪的不同部分中有多个这种检查)。我相信这是fiber.testcancel的基本用例,除了讨论它的设计是否可用之外。

附注:是的,偶尔会有这样的例外情况没有记录在案。至少我在fiber页面上找不到任何东西

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62262458

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档