File: recursive.yo

package info (click to toggle)
c%2B%2B-annotations 13.02.02-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,576 kB
  • sloc: cpp: 25,297; makefile: 1,523; ansic: 165; sh: 126; perl: 90; fortran: 27
file content (53 lines) | stat: -rw-r--r-- 3,268 bytes parent folder | download | duplicates (3)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Like ordinary functions coroutines can recursively be called. An
    hi(coroutine: essential characteristic) essential characteristic of
coroutines is that when they're used they look no different than ordinary
functions. It's merely in the implementation that coroutines differ from
ordinary functions.

For starters, consider a very simple interactive program that produces a
series of numbers until the user ends the program or enters tt(q):
    verbinsert(-ns4 //main demo/recursive/main.cc)
    At line 3 the tt(recursiveCoro) coroutine is called, returning its handler
tt(rec). In line 7 its member tt(next) is called, returning the next value
produced by tt(recursiveCoro). The function tt(recursiveCoro) could
have been any function returning an object of a class that has a tt(next)
member. For now ignoring recursion, tt(recursiveCoro) could look like this:
    verbinsert(-ans4 demo/recursive/recursivecoro.1)
    The coroutine merely produces the sequence of non-negative integral
numbers, starting at 0. Its two for-loops (lines 10 and 15) are there merely
for illustrative purposes, and the recursive call will be placed between those
for-loops. The variable tt(s_value) is defined outside the coroutine (instead
of using tt(static s_value = 0) inside), as recursively called coroutines must
all access the same tt(s_value) variable. There's no magic here: just two
for-statements in a continuously iterating while-statement.

The interface of the returned tt(Recursive) object isn't complex either:
    verbinsert(-ns4 //interface demo/recursive/recursive/recursive.h)
    The required members of its tt(State) class are available in
tt(PromiseBase) (cf. section ref(STATEBASE)) and do not have to be
modified. As tt(recursiveCoro co_yields) values, the tt(State::yield_value) 
member stores those values in its tt(d_value) data member:
    verbinsert(-s4 //yv demo/recursive/recursive/state.cc)
    Its member tt(value) is an accessor, returning tt(d_value). When recursion
is used the recursive calls end at some point. When tt(recursiveCoro)
functions end tt(State::return_void) is called. It doesn't have to do
anything, so tt(PromiseBase's) empty implementation perfectly does the job.

The tt(Recursive) handling class's own interface starts at line 12. Its
tt(d_handle) data member (line 14) is initialized by its constructor (line
19), which is all the constructor has to do. The handler's destructor only has
to call tt(d_handle.destroy()) to return the memory used by its tt(State)
object.

The remaining members are tt(next) and tt(done). These, too, are implemented
straight-forwardly. The member tt(done) will shortly be used in the recursive
implementation of tt(recursiveCoro), and it just returns the value returned by
tt(d_handle.done()).

When the member tt(next) is called the coroutine is in its suspended state
(which is what happens when it's initially called (cf. line 3 in the above
tt(main) function) and thereafter when it uses tt(co_yield) (lines 11 and 16
in the above implementation of tt(recursiveCoro))). So it resumes the
coroutine, and when the coroutine is again suspended, it returns the (next
available) value stored in the handler's tt(State) object:
    verbinsert(-s4 //next demo/recursive/recursive/recursive.cc)