source: doc/papers/concurrency/examples/Fib.cpp@ 34c32f0

ADT ast-experimental enum forall-pointer-decay pthread-emulation qualifiedEnum
Last change on this file since 34c32f0 was 571bf75, checked in by tdelisle <tdelisle@…>, 7 years ago

Clean existing coroutines using std::experimental::suspend_never and fixed Format coroutines to use RAII

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