반응형

코루틴(Coroutine)
루아에서 코루틴은 생성(Create), 재개(resume) 및 양보(yield) 세 가지 동작을 기본으로 제공한다.
루아의 다른 값과 마찬가지로 코루틴은 가비지 컬렉션에 의해 삭제된다.
생성(Create)
local co = coroutine.create(function() ... end)
function hello()
for i = 1, 5 do
print("Hello, " .. i)
end
end
local hello_co = coroutine.create(hello)
coroutine.create
함수는 새 코루틴을 만들고 실행을 위해 별도의 스택을 할당한다.- 실행할 함수를 인수로 받으며 해당 코루틴에 대한 참조를 반환한다.
- 생성 후 코루틴의 상태는 정지(Suspended) 상태에 있다.
- 익명 함수를 인수로 전달할 수도 있다.
재개(Resume)
local status, value = coroutine.resume(hello_co)
coroutine.resume
함수는 코루틴을 활성화하고, 필요한 첫 번째 인수로 코루틴 참조를 받는다.- 코루틴이 재개되면 중지된 이후 지점부터 실행되며 정지되거나 종료될 때까지 실행된다.
- 코루틴이 정상적으로 종료되면
coroutine.resume
함수는 실행 성공 여부와 코루틴 메인 함수에서 반환된 모든 값을 반환한다. - 코루틴이 한 번 종료되면 재실행 할 수 없으므로 다시 생성해서 사용해야 한다.
양보(Yield)
local co1 = coroutine.create(function()
for i = 1, 5 do
print("co1: " .. i)
coroutine.yield()
end
end)
local co2 = coroutine.create(function()
for i = 1, 5 do
print("co2: " .. i)
coroutine.yield()
end
end)
for i = 1, 5 do
coroutine.resume(co1)
coroutine.resume(co2)
end
coroutine.yield
함수를 실행하면 코루틴은 일시 중단되며 코루틴의 실행 상태가 저장된다.- 중단 이후 코루틴을 재개하면 코루틴이 정지된 정확한 시점부터 실행이 계속된다.
래핑(Wrap)
이 외에도 coroutine.wrap
함수가 존재한다. 해당 함수는 기존 코루틴과 달리 코루틴 생성 이후 재개 함수를 명시적으로 사용할 필요가 없으며 wrap 함수의 간단한 내부 구현은 아래와 같다.
function wrap(f)
local co = coroutine.create(f)
return function(v)
status, val = coroutine.resume(co, v)
if status then return val
else error(val)
end
end
end
- 이 보조 함수는
corutine.resume
실행 함수를 반환하며 코루틴을 간편하게 사용할 수 있도록 설계되어 있다.
local co = coroutine.wrap(
function(a)
local c = coroutine.yield(a + 2)
return c * 2
end)
b = co(20)
print(b)
d = co(b + 1)
print(d)
--[[
Output:
22
46
]]
- 코루틴을 생성하고 처음으로 실행하면
yield
에 의해 일시 중단되고 22 (a + 2)의 값으로 반환된다. - 두 번째 실행 되었을 때 로컬 변수 c 는 23 (b + 1) 값을 얻게 되고 최종적으로 46 (c * 2) 값이 출력되고 코루틴이 종료된다.
상태(Status)
local function hello()
print("Hello, ")
coroutine.yield()
print("Lua")
end
local co = coroutine.create(hello)
print(coroutine.status(co)) -- suspended
coroutine.resume(co)
print(coroutine.status(co)) -- suspended
coroutine.resume(co)
print(coroutine.status(co)) -- dead
- 코루틴의 상태에는
suspended
,running
,dead
,normal
이 있다. coroutine.status
함수로 현재 코루틴의 상태를 문자열로 확인할 수 있다.suspended
상태는 처음 생성되었거나 yield에 의해 일시 중단된 상태다.running
상태는 현재 코루틴이 동작중인 상태이며 주로 코루틴 내부에서 확인된다.dead
상태는 코루틴이 완료되어 종료된 상태다.normal
상태는 코루틴이 재개되기를 기다리는 상태이며 외부에서 확인 가능하나 코루틴의 특성 때문에 확인하기 힘들다.
코루틴 사용 예시
function producer()
for i = 1, 5 do
coroutine.yield(i)
end
end
function consumer(producer_co)
while true do
local success, value = coroutine.resume(producer_co)
if coroutine.status(producer_co) == "suspended" then
print("Consumed: ", value)
else
break;
end
end
end
local producer_co = coroutine.create(producer)
consumer(producer_co)