With Boost.Coroutine it is possible to use coroutines in C++. Coroutines are a feature of other programming languages, which often use the keyword yield
for coroutines. In these programming languages, yield
can be used like return
. However, when yield
is used, the function remembers the location, and if the function is called again, execution continues from that location.
C++ doesn’t define a keyword yield
. However, with Boost.Coroutine it is possible to return from functions and continue later from the same location. The Boost.Asio library also uses Boost.Coroutine and benefits from coroutines.
There are two versions of Boost.Coroutine. This chapter introduces the second version, which is the current version. This version has been available since Boost 1.55.0 and replaces the first one.
Example 51.1 defines a function, cooperative()
, which is called from main()
as a coroutine.cooperative()
returns to main()
early and is called a second time. On the second call, it continues from where it left off.
To use cooperative()
as a coroutine, the types pull_type
and push_type
are used. These types are provided by boost::coroutines::coroutine
, which is a template that is instantiated with void
in Example 51.1.
To use coroutines, you need pull_type
and push_type
. One of these types will be used to create an object that will be initialized with the function you want to use as a coroutine. The other type will be the first parameter of the coroutine function.
Example 51.1 creates an object named source of type pull_type
in main()
. cooperative()
is passed to the constructor. push_type
is used as the sole parameter in the signature ofcooperative()
.
When source is created, the function cooperative()
, which is passed to the constructor, is immediately called as a coroutine. This happens because source is based on pull_type
. Ifsource was based on push_type
, the constructor wouldn’t call cooperative()
as a coroutine.
cooperative()
writes Hello
to standard output. Afterwards, the function accesses sink as if it were a function. This is possible because push_type
overloads operator()
. Whilesource in main()
represents the coroutine cooperative()
, sink in cooperative()
represents the function main()
. Calling sink makes cooperative()
return, and main()
continues from where cooperative()
was called and writes a comma to standard output.
Then, main()
calls source as if it were a function. Again, this is possible because of the overloaded operator()
. This time, cooperative()
continues from the point where it left off and writes world
to standard output. Because there is no other code in cooperative()
, the coroutine ends. It returns to main()
, which writes an exclamation mark to standard output.
The result is that Example 51.1 displays Hello, world!
You can think of coroutines as cooperative threads. To a certain extent, the functions main()
and cooperative()
run concurrently. Code is executed in turns in main()
andcooperative()
. Instructions inside each function are executed sequentially. Thanks to coroutines, a function doesn’t need to return before another function can be executed.
Example 51.2 is similar to the previous example. This time the templateboost::coroutines::coroutine
is instantiated with int
. This makes it possible to return anint
from the coroutine to the caller.
The direction the int
value is passed depends on where pull_type
and push_type
are used. The example uses pull_type
to instantiate an object in main()
. cooperative()
has access to an object of type push_type
. push_type
sends a value, and pull_type
receives a value; thus, the direction of the data transfer is set.
cooperative()
calls sink, with a parameter of type int
. This parameter is required because the coroutine was instantiated with the data type int
. The value passed to sink is received from source in main()
by using the member function get()
, which is provided bypull_type
.
Example 51.2 also illustrates how a function with multiple parameters can be used as a coroutine. cooperative()
has an additional parameter of type int
, which can’t be passed directly to the constructor of pull_type
. The example uses std::bind()
to link the function with pull_type
.
The example writes 1
and 2
followed by end
to standard output.
Example 51.3 uses push_type
in main()
and pull_type
in cooperative()
, which means data is transferred from the caller to the coroutine.
This example illustrates how multiple values can be passed. Boost.Coroutine doesn’t support passing multiple values, so a tuple must be used. You need to pack multiple values into a tuple or another structure.
Example 51.3 displays 0 aaa
, 1 bbb
, and end
.
A coroutine returns immediately when an exception is thrown. The exception is transported to the caller of the coroutine where it can be caught. Thus, exceptions are no different than with regular function calls.
Example 51.4 shows how this works. This example will write the string error
to standard output.
출처 - 부스트씨쁠쁠라이브러리
'뻘소리' 카테고리의 다른 글
컨텍스트 스위칭(Context Switching) (0) | 2016.10.04 |
---|---|
람다 대수 (0) | 2016.08.21 |
비구조적 프로그래밍 (0) | 2016.08.18 |
아키텍처 프로그래밍 (0) | 2016.08.18 |
제네릭 프로그래밍 (0) | 2016.08.18 |