อะไรคือ coroutine

ปกติแล้วเวลาเราเขียน function สัก function นึง มันจะรันตั้งแต่จนจบถึงจะสามารถรัน function ต่อๆไปได้เช่น

FirstFunction() // <-- อันนี้ต้องรันจนเสร็จก่อนถึงจะไป SecondFunction ได้
SecondFunction()

แต่ coroutine ทำให้แต่ละ function สามารถ cooperate (ทำงานร่วมกันได้) โดยที่แต่ละ function ยังจำได้ว่าครั้งล่าสุดอยู่ตรงไหนละสามารถทำงานต่อได้โดยไม่ต้องเริ่มใหม่

เช่นตัวอย่างนี้จาก Wikipedia

var q := new queue

coroutine produce
    loop
        while q is not full
            create some new items
            add the items to q
        yield to consume

coroutine consume
    loop
        while q is not empty
            remove some items from q
            use the items
        yield to produce

call produce

สมมุติว่า queue สามารถรับได้ 10 items มากสุดแต่เรามี item ที่ต้อง create 20 อัน flow การทำงานจะเริ่มจาก

  1. produce ทำการ loop สร้าง item 10 อันใน queue (item 1-10)
  2. พอครบก็ yield ไปให้ consume เอา queue ออกจนเหลือ 0
  3. product ทำการ loop ต่ออีก 10 item (item 11-20)
  4. yield การทำงานไปให้ consume เพื่อ dequeue ออกทั้งหมด

จะเห็นได้ว่าแต่ละ function จะสามารถจำ state ของตัวเองได้เมื่อถูก yield และเมื่อถูก call อีกครั้งก็จะสามารถกลับไปรันต่อตรงจุดเดิม

ระวังเข้าใจผิดว่า coroutine คือการทำแบบ parallel นะครับ! ตามที่อธิบายด้านบน coroutine ทำแค่ปล่อย (yield) สิ่งที่ตัวเองรันอยู่ให้ function อื่นรันก่อนแล้วจำสิ่งที่ตัวเองทำอยู่ไว้ เมื่อคนอื่นมา call อีกครั้งถึงจะรันต่อจากจุดเดิม