📜  Lua-协程

📅  最后修改于: 2020-10-16 05:13:17             🧑  作者: Mango


介绍

协程本质上是协作的,它允许两种或多种方法以受控方式执行。对于协程,在任何给定时间,只有一个协程运行,并且此运行的协程仅在明确要求暂停时才暂停其执行。

上面的定义可能看起来很模糊。让我们假设我们有两种方法,一种是主程序方法,另一种是协程。当我们使用resume函数调用协程时,它开始执行,而当我们调用yield函数,它暂停执行。同样,相同的协程可以从挂起的位置继续执行另一个恢复函数调用。这个过程可以持续到协程执行结束为止。

协程中可用的功能

下表列出了Lua中协程的所有可用功能及其相应用途。

Sr.No. Method & Purpose
1

coroutine.create (f)

Creates a new coroutine with a function f and returns an object of type “thread”.

2

coroutine.resume (co [, val1, …])

Resumes the coroutine co and passes the parameters if any. It returns the status of operation and optional other return values.

3

coroutine.running ()

Returns the running coroutine or nil if called in the main thread.

4

coroutine.status (co)

Returns one of the values from running, normal, suspended or dead based on the state of the coroutine.

5

coroutine.wrap (f)

Like coroutine.create, the coroutine.wrap function also creates a coroutine, but instead of returning the coroutine itself, it returns a function that, when called, resumes the coroutine.

6

coroutine.yield (…)

Suspends the running coroutine. The parameter passed to this method acts as additional return values to the resume function.

让我们看一个例子来了解协程的概念。

co = coroutine.create(function (value1,value2)
   local tempvar3 = 10
   print("coroutine section 1", value1, value2, tempvar3)
    
   local tempvar1 = coroutine.yield(value1+1,value2+1)
   tempvar3 = tempvar3 + value1
   print("coroutine section 2",tempvar1 ,tempvar2, tempvar3)
    
   local tempvar1, tempvar2= coroutine.yield(value1+value2, value1-value2)
   tempvar3 = tempvar3 + value1
   print("coroutine section 3",tempvar1,tempvar2, tempvar3)
   return value2, "end"
    
end)

print("main", coroutine.resume(co, 3, 2))
print("main", coroutine.resume(co, 12,14))
print("main", coroutine.resume(co, 5, 6))
print("main", coroutine.resume(co, 10, 20))

当我们运行上面的程序时,我们将得到以下输出。

coroutine section 1    3    2    10
main    true    4    3
coroutine section 2    12    nil    13
main    true    5    1
coroutine section 3    5    6    16
main    true    2    end
main    false    cannot resume dead coroutine

上面的示例做什么?

如前所述,我们使用resume函数来启动操作,并使用yield函数来停止操作。另外,您可以看到协程的resume函数接收到多个返回值。

  • 首先,我们创建一个协程并将其分配给变量名co,协程将两个变量作为其参数。

  • 当我们调用第一个resume函数,值3和2将保留在临时变量value1和value2中,直到协程结束。

  • 为了使您理解这一点,我们使用了tempvar3,该变量最初为10,随后的协程调用将其更新为13和16,因为在协程执行过程中value1始终保留为3。

  • 第一个coroutine.yield向resume函数返回两个值4和3,这是通过更新yield语句中的输入参数3和2获得的。它还接收协程执行的正确/错误状态。

  • 关于协程的另一件事是在上面的示例中如何处理恢复调用的下一个参数;您会看到变量coroutine.yield接收到下一个调用参数,这为保留现有参数值的新操作提供了一种强大的方法。

  • 最后,一旦协程中的所有语句执行完毕,后续调用将返回false,并且“无法恢复死的协程”语句作为响应。

协程的另一个例子

让我们看一个简单的协程,它在yield函数和resume函数的帮助下返回1到5之间的数字。如果不存在协程,它将创建协程,否则将恢复现有协程。

function getNumber()
   local function getNumberHelper()
      co = coroutine.create(function ()
      coroutine.yield(1)
      coroutine.yield(2)
      coroutine.yield(3)
      coroutine.yield(4)
      coroutine.yield(5)
      end)
      return co
   end
    
   if(numberHelper) then
      status, number = coroutine.resume(numberHelper);
        
      if coroutine.status(numberHelper) == "dead" then
         numberHelper = getNumberHelper()
         status, number = coroutine.resume(numberHelper);
      end
        
      return number
   else
      numberHelper = getNumberHelper()
      status, number = coroutine.resume(numberHelper);
      return number
   end
    
end

for index = 1, 10 do
   print(index, getNumber())
end

当我们运行上面的程序时,我们将得到以下输出。

1    1
2    2
3    3
4    4
5    5
6    1
7    2
8    3
9    4
10    5

通常将协程与多程序语言的线程进行比较,但是我们需要了解,协程具有类似的线程功能,但是它们一次只能执行一个,而不会同时执行。

我们通过暂时保留某些信息来控制程序的执行顺序以满足需求。将全局变量与协程一起使用为协程提供了更大的灵活性。