source: doc/papers/concurrency/c++-cor/fib.cpp@ 79b018f3

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 79b018f3 was be3416d, checked in by tdelisle <tdelisle@…>, 7 years ago

Added more examples of c++20 coroutines

  • Property mode set to 100644
File size: 2.3 KB
Line 
1#include "base.hpp"
2
3#include <algorithm>
4#include <iterator>
5#include <vector>
6
7template<typename T>
8struct cor_range {
9 struct promise_type {
10 T _value;
11
12 cor_range get_return_object() {
13 return cor_range(std::experimental::coroutine_handle<promise_type>::from_promise(*this));
14 }
15
16 auto initial_suspend() { return suspend_always(); }
17 auto final_suspend() { return suspend_always(); }
18
19 void return_value(T value) {
20 _value = value;
21 }
22
23 auto yield_value(T value) {
24 _value = value;
25 return suspend_always();
26 }
27
28 void unhandled_exception() {}
29 };
30
31 std::experimental::coroutine_handle<promise_type> _coroutine = nullptr;
32
33 explicit cor_range(std::experimental::coroutine_handle<promise_type> coroutine)
34 : _coroutine(coroutine)
35 {}
36
37 ~cor_range() {
38 if(_coroutine) { _coroutine.destroy(); }
39 }
40
41 cor_range() = default;
42 cor_range(cor_range const &) = delete;
43 cor_range& operator=(cor_range const &) = delete;
44
45 cor_range(cor_range&& other) {
46 std::swap(_coroutine, other._coroutine);
47 }
48
49 cor_range& operator=(cor_range&& other) {
50 if(&other != this) {
51 _coroutine = other._coroutine;
52 other._coroutine = nullptr;
53 }
54 return *this;
55 }
56
57 T next() {
58 _coroutine.resume();
59 return _coroutine.promise()._value;
60 }
61
62 struct iterator : std::iterator<std::input_iterator_tag, T> {
63 std::experimental::coroutine_handle<promise_type> _coroutine = nullptr;
64
65 iterator() = default;
66 explicit iterator(std::experimental::coroutine_handle<promise_type> coroutine)
67 : _coroutine(coroutine)
68 {}
69
70 iterator& operator++() {
71 _coroutine.resume();
72 return *this;
73 }
74
75 T const & operator*() const {
76 return _coroutine.promise()._value;
77 }
78 };
79
80 iterator begin() {
81 if(_coroutine) {
82 _coroutine.resume();
83 if(_coroutine.done()) { return end(); }
84 }
85
86 return iterator{ _coroutine };
87 }
88
89 iterator end() { return iterator{}; }
90};
91
92cor_range<int> fib() {
93 int fn;
94 fn = 0; int fn1 = fn; co_yield fn;
95 fn = 1; int fn2 = fn1; fn1 = fn; co_yield fn;
96 for(;;) {
97 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; co_yield fn;
98 }
99}
100
101int main() {
102 {
103 auto f1 = fib();
104 auto f2 = fib();
105 for(int i = 0; i < 10; i++) {
106 std::cout << f1.next() << " " << f2.next() << std::endl;
107 }
108 }
109
110 {
111 auto f1 = fib();
112 std::vector<int> fibs;
113 std::copy_n(f1.begin(), 10, std::back_inserter(fibs));
114
115 for(auto i : fibs) {
116 std::cout << i << std::endl;
117 }
118 }
119}
Note: See TracBrowser for help on using the repository browser.