Lua Academy · Oppitunti

Korutiinin tila

Tarkistakaa korutiinin tila coroutine.status-funktiolla: running, suspended tai dead.

Oppitunti 3/412 vaihetta

Korutiinin tila on ilmainen Lua Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Lua Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Lua Academy-kurssilla on yhteensä 4 oppituntia.

Korutiinien neljä tilaa

Korutiinilla voi olla neljä tilaa: keskeytetty (luotu tai yield-kutsulla keskeytetty ja suoritusvuoroa odottava), suorituksessa (suoritetaan parhaillaan), normal (pysäytettynä toisen korutiinin suorittamisen ajaksi) ja dead (suoritettu loppuun tai päättynyt virheeseen). Kysykää tila kutsulla coroutine.status(co).

local co = coroutine.create(function()
  print(coroutine.status(coroutine.running()))  -- running
  coroutine.yield()
end)

print(coroutine.status(co))  -- suspended
coroutine.resume(co)          -- prints: running
print(coroutine.status(co))  -- suspended
coroutine.resume(co)
print(coroutine.status(co))  -- dead

"normal"-tila

Korutiini siirtyy tilaan "normal", kun se jatkaa toista korutiinia. Se ei ole suorituksessa (toinen korutiini on), mutta se ei ole myöskään keskeytetty — se odottaa, että jatkettu korutiini tekee yield-kutsun. Tämä tila on harvinainen, mutta sen ymmärtäminen on tärkeää monimutkaisissa korutiinikaavioissa.

local inner, outer

inner = coroutine.create(function()
  print("outer status:", coroutine.status(outer))  -- normal
  coroutine.yield()
end)

outer = coroutine.create(function()
  coroutine.resume(inner)
end)

coroutine.resume(outer)
-- prints: outer status: normal

Tilan tarkistaminen ennen jatkamista

Tarkistakaa korutiinin tila aina ennen sen jatkamista, erityisesti silmukoissa. Päättyneen korutiinin jatkaminen aiheuttaa virheen. Myös suorituksessa olevan korutiinin jatkaminen aiheuttaa virheen, koska se johtaisi päättymättömään rekursioon.

local function safeResume(co, ...)
  local status = coroutine.status(co)
  if status == "dead" then
    return false, "cannot resume dead coroutine"
  end
  if status == "running" then
    return false, "cannot resume running coroutine"
  end
  return coroutine.resume(co, ...)
end

Tila virheen jälkeen

Kun korutiinin rungossa syntyy käsittelemätön virhe, coroutine.resume palauttaa arvot false ja virheviestin. Korutiini siirtyy tilaan "dead". Sitä ei voi käynnistää uudelleen — uutta yritystä varten on luotava uusi korutiini.

local co = coroutine.create(function()
  error("something went wrong")
end)

local ok, err = coroutine.resume(co)
print(ok, err)                      -- false  ...: something went wrong
print(coroutine.status(co))         -- dead

-- Cannot resume dead coroutine:
local ok2, err2 = coroutine.resume(co)
print(ok2, err2)  -- false  cannot resume dead coroutine

coroutine.isyieldable

coroutine.isyieldable() palauttaa arvon true, jos käynnissä oleva korutiini voi tehdä yield-kutsun. Se palauttaa arvon false pääsäikeessä ja sellaisissa C-funktioissa, jotka eivät tue yield-kutsuja. Tarkistakaa tämä aina ennen yield-kutsua, jos suorituskonteksti on epävarma.

local co = coroutine.create(function()
  print("isyieldable:", coroutine.isyieldable())  -- true
  coroutine.yield()
end)

coroutine.resume(co)

-- In main thread:
print("isyieldable:", coroutine.isyieldable())  -- false
-- coroutine.yield()  -- ERROR in main thread

Korutiinijoukon valvonta

Seuratkaa korutiinipoolia ja poistakaa päättyneet korutiinit jokaisen jatkamiskierroksen jälkeen. Tämä muodostaa tehtäväajastimen perustan.

local function makeWorker(n, name)
  return coroutine.create(function()
    for i = 1, n do
      print(name, "step", i)
      coroutine.yield()
    end
  end)
end

local workers = {
  makeWorker(2, "fast"),
  makeWorker(4, "slow"),
}

while #workers > 0 do
  local alive = {}
  for _, co in ipairs(workers) do
    coroutine.resume(co)
    if coroutine.status(co) ~= "dead" then
      alive[#alive+1] = co
    end
  end
  workers = alive
end

Korutiinien virheenkorjaus

Instrumentoikaa korutiineihin perustuva koodi ja tehkää sen virheenkorjausta tilantarkistusten avulla. Tulostakaa tilasiirtymät ymmärtääksenne suoritusvirran. Monimutkaisissa järjestelmissä voitte nimetä korutiinit wrapper-taulukon avulla, jolloin virheenkorjaustulosteista tulee selkeämpiä.

local function namedCo(name, fn)
  local co = coroutine.create(fn)
  return {
    co = co,
    name = name,
    resume = function(self, ...)
      print("[" .. self.name .. "] resume")
      local results = table.pack(coroutine.resume(self.co, ...))
      print("[" .. self.name .. "] status: " .. coroutine.status(self.co))
      return table.unpack(results, 1, results.n)
    end
  }
end

local worker = namedCo("worker1", function()
  coroutine.yield()
end)
worker:resume()
worker:resume()

Päättyneiden korutiinien käynnistäminen uudelleen

Kun korutiini on päättynyt, sitä ei voi jatkaa. Sen "käynnistämiseksi uudelleen" on luotava uusi korutiini samasta funktiosta. Yleinen malli on tehdasfunktio, joka luo tarvittaessa uuden korutiinin.

local function makeCounter(start, step)
  return coroutine.wrap(function()
    local n = start or 0
    while true do
      coroutine.yield(n)
      n = n + (step or 1)
    end
  end)
end

local count = makeCounter(0, 2)
for i = 1, 5 do io.write(count() .. " ") end
print()  -- 0 2 4 6 8

-- "Restart" by creating a new one
count = makeCounter(100)
print(count())   -- 100

Coroutine.wrapin virhekäyttäytyminen

Kun wrapilla kääritty korutiini aiheuttaa virheen, virhe välittyy wrapper-funktiokutsun ulkopuolelle. Toisin kuin coroutine.resume, joka palauttaa arvot false ja virheen, wrap-funktion palauttamat funktiot nostavat virheen suoraan. Käyttäkää pcall-kutsua wrap-kutsujen ympärillä, jos virheet on otettava kiinni.

local gen = coroutine.wrap(function()
  coroutine.yield(1)
  error("oops")
  coroutine.yield(2)  -- never reached
end)

print(gen())   -- 1 (ok)
local ok, err = pcall(gen)
print(ok, err) -- false  ...: oops
-- Subsequent call: dead coroutine
ok, err = pcall(gen)
print(ok, err) -- false  cannot resume dead coroutine

isyieldable ja status

Korutiinikontekstin tarkasteluun on kaksi tapaa: coroutine.status(co) ilmoittaa tietyn korutiinin tilan, kun taas coroutine.isyieldable() kertoo, voiko nykyinen suorituskonteksti tehdä yield-kutsun. Tarkistakaa muiden korutiinien tila status-kutsulla ja se, voitteko tehdä yield-kutsun turvallisesti, isyieldable-kutsulla.

local function maybeYield()
  if coroutine.isyieldable() then
    coroutine.yield()
  else
    -- in main thread or non-yieldable context
    print("cannot yield here")
  end
end

maybeYield()  -- prints "cannot yield here" (main thread)

local co = coroutine.create(maybeYield)
coroutine.resume(co)   -- yields successfully

Pikatarkistus

Mihin tilaan korutiini siirtyy, kun sen runkofunktio on suoritettu loppuun?

Kertaus: korutiinin tila

Yhteenveto:

  • Tilat: keskeytetty → suorituksessa ↔ normal → dead
  • coroutine.status(co) palauttaa tilan merkkijonona
  • Dead tarkoittaa suoritettua loppuun tai virheeseen päättynyttä; korutiinia ei voi jatkaa
  • coroutine.isyieldable() tarkistaa, voiko nykyinen konteksti tehdä yield-kutsun
  • Tarkistakaa tila aina ennen jatkamista silmukoissa
  • wrapin virheet välittyvät suoraan; resume palauttaa arvot false ja err
Aloita maksutta

Opi Lua tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
40
Oppitunnit
159

Usein kysytyt kysymykset

Onko oppitunti ”Korutiinin tila” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Lua Academy-oppimispolun 3 oppituntia, myös oppitunnin “Korutiinin tila”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Lua Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Korutiinin tila”?

Tarkistakaa korutiinin tila coroutine.status-funktiolla: running, suspended tai dead. Harjoittelet Lua Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Lua Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Lua Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Korutiinin tila”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Lua Academy-oppitunnilla?

Kyllä. Jokainen Lua Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Käytävien luominen
  2. resume ja yield
  3. Korutiinin tila
  4. Tuottaja–kuluttaja-malli
← Takaisin: Lua Academy