What is coroutine

As the name implies, coroutine refers to co-operative routine. It allows you to suspending and resuming execution at different locations. So, it’s essentially just context switching. Not surprisingly, coroutine is implemented in primitives like setjmp/longjump or ucontext in low level.

In many senarioes, coroutine is a more light-weight alternative of threads. For programming languages with GIL (like Python), coroutine would used to handle concurrency.

Producer and consumer problem

Let’s take a look at classic “producer-consumer” problem. At each time, one coroutine produce products and add them into queue, the other coroutine take products from queue and use it (hmm, sounds like video buffering, right?).

The code below assumes you already have some knowledge of generator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import time
import random

def coroutine(func):
# A wrapper to convert function into generator
# From David Beazley
def start(*args,**kwargs):
cr = func(*args,**kwargs)
cr.next()
return cr
return start

def producer(target):
while True:
time.sleep(1)
data = random.randint(1, 10)
print ("# producer: sending data {}".format(data))
target.send(data)

@coroutine
def consumer():
while True:
data = yield
print ("# consumer: receving data {}".format(data))

if __name__ == '__main__':
g_consumer = consumer()
producer(g_consumer)

Simple enough, send() is a built-in function of generator. The producer send data to consumer, consumer receives data from yield.

Coroutine usage

Yes, the famous concurrency library gevent is based on coroutine.

PEP 342: Coroutines via Enhanced Generators

一个“蝇量级” C 语言协程库

General concepts: concurrency, parallelism, threads and processes

A Curious Course on Coroutines and Concurrency