source: doc/papers/concurrency/examples/Fib.cpp @ cc7bbe6

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since cc7bbe6 was 571bf75, checked in by tdelisle <tdelisle@…>, 6 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.