Lua coroutine



Apakah coroutine?

Lua coroutine adalah serupa dengan utas: ia mempunyai tindanan bebas, pembolehubah tempatan bebas dan penunjuk arahan bebas, sambil berkongsi pembolehubah global dan kebanyakan perkara lain dengan coroutine lain.

Kolaborasi ialah fungsi yang sangat berkuasa, tetapi ia juga sangat rumit untuk digunakan.

Perbezaan antara thread dan coroutine

Perbezaan utama antara thread dan coroutine ialah program dengan berbilang thread boleh menjalankan beberapa thread pada masa yang sama, manakala coroutine perlu dijalankan dengan kerjasama setiap lain.

Hanya satu coroutine sedang berjalan pada bila-bila masa dan coroutine yang sedang berjalan hanya akan digantung apabila diminta untuk menggantung secara jelas.

Coroutine agak serupa dengan berbilang benang yang disegerakkan dan beberapa utas menunggu kunci benang yang sama agak serupa dengan kerjasama.

Tatabahasa Asas

方法描述
coroutine.create()创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用
coroutine.resume()重启coroutine,和create配合使用
coroutine.yield()挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果
coroutine.status()查看coroutine的状态
注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序
coroutine.wrap()创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复
coroutine.running()返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号

Contoh berikut menunjukkan penggunaan setiap kaedah di atas:

-- coroutine_test.lua 文件
co = coroutine.create(
    function(i)
        print(i);
    end
)
 
coroutine.resume(co, 1)   -- 1
print(coroutine.status(co))  -- dead
 
print("----------")
 
co = coroutine.wrap(
    function(i)
        print(i);
    end
)
 
co(1)
 
print("----------")
 
co2 = coroutine.create(
    function()
        for i=1,10 do
            print(i)
            if i == 3 then
                print(coroutine.status(co2))  --running
                print(coroutine.running()) --thread:XXXXXX
            end
            coroutine.yield()
        end
    end
)
 
coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3
 
print(coroutine.status(co2))   -- suspended
print(coroutine.running())
 
print("----------")

Output pelaksanaan contoh di atas ialah:

1
dead
----------
1
----------
1
2
3
running
thread: 0x7fb801c05868	false
suspended
thread: 0x7fb801c04c88	true
----------

Ia boleh dilihat daripada coroutine.running bahawa asas pelaksanaan coroutine ialah benang.

Apabila membuat coroutine, acara didaftarkan dalam urutan baharu.

Apabila resume digunakan untuk mencetuskan acara, fungsi coroutine create dilaksanakan Apabila hasil ditemui, ini bermakna menggantung urutan semasa dan menunggu resume untuk mencetuskan acara itu semula.

Seterusnya kami menganalisis contoh yang lebih terperinci:

function foo (a)
    print("foo 函数输出", a)
    return coroutine.yield(2 * a) -- 返回  2*a 的值
end
 
co = coroutine.create(function (a , b)
    print("第一次协同程序执行输出", a, b) -- co-body 1 10
    local r = foo(a + 1)
     
    print("第二次协同程序执行输出", r)
    local r, s = coroutine.yield(a + b, a - b)  -- a,b的值为第一次调用协同程序时传入
     
    print("第三次协同程序执行输出", r, s)
    return b, "结束协同程序"                   -- b的值为第二次调用协同程序时传入
end)
        
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("--分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")

Output pelaksanaan contoh di atas ialah:

第一次协同程序执行输出	1	10
foo 函数输出	2
main	true	4
--分割线----
第二次协同程序执行输出	r
main	true	11	-9
---分割线---
第三次协同程序执行输出	x	y
main	true	10	结束协同程序
---分割线---
main	false	cannot resume dead coroutine
---分割线---

Contoh di atas diteruskan seperti berikut:

  • Panggil resume untuk membangunkan coroutine Operasi resume kembali benar jika berjaya, jika tidak ia kembali palsu

  • Coroutine berjalan; 🎜>

    Jalankan ke penyata hasil;
  • hasil menutup coroutine, dan resume pertama kembali; (Nota: pulangan hasil di sini, dan parameter adalah parameter resume )
  • Sambung semula untuk kali kedua dan bangunkan coroutine semula; (Nota: Antara parameter resume di sini, kecuali untuk parameter pertama, parameter yang selebihnya akan digunakan sebagai parameter hasil)
  • hasil pulangan;
  • Coroutine terus berjalan; untuk menjalankan dan terus memanggil kaedah resume selepas selesai, kemudian Output: tidak boleh menyambung semula coroutine mati
  • Gabungan kuat resume dan hasil ialah resume sedang dalam proses utama, dan ia lulus status luaran (data) ke dalam coroutine; dan hasil Status dalaman (data) dikembalikan kepada proses utama.
  • Masalah Pengeluar-Pengguna

  • Kini saya menggunakan coroutine Lua untuk menyelesaikan masalah pengeluar-pengguna klasik.
local newProductor

function productor()
     local i = 0
     while true do
          i = i + 1
          send(i)     -- 将生产的物品发送给消费者
     end
end

function consumer()
     while true do
          local i = receive()     -- 从生产者那里得到物品
          print(i)
     end
end

function receive()
     local status, value = coroutine.resume(newProductor)
     return value
end

function send(x)
     coroutine.yield(x)     -- x表示需要发送的值,值返回以后,就挂起该协同程序
end

-- 启动程序
newProductor = coroutine.create(productor)
consumer()

Hasil keluaran contoh di atas ialah:

1
2
3
4
5
6
7
8
9
10
11
12
13
……