source: doc/papers/concurrency/examples/Format.cpp @ 13b1b1d

arm-ehcleanup-dtorsjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since 13b1b1d was 13b1b1d, checked in by tdelisle <tdelisle@…>, 3 years ago

C++ Format coroutine now "properly" destroys itself

  • Property mode set to 100644
File size: 1.9 KB
Line 
1
2#include "base.hpp"
3
4struct fmt_cor {
5        struct promise_type {
6                char _value;
7                struct locals {
8                        int g, b;
9                } * _l;
10
11                fmt_cor get_return_object() {
12                        return fmt_cor(std::experimental::coroutine_handle<promise_type>::from_promise(*this));
13                }
14
15                auto initial_suspend() { return suspend_never(); }
16                auto final_suspend()   { return suspend_always(); }
17
18                void return_void() {}
19                void unhandled_exception() {}
20
21                auto yield_value(locals & l) {
22                        _l = &l;
23                        return suspend_never();
24                }
25        };
26
27        struct get {
28                promise_type * _promise = nullptr;
29
30                bool await_ready() noexcept {
31                        return false;
32                }
33
34                void await_suspend(std::experimental::coroutine_handle<promise_type> _coroutine) noexcept {
35                        _promise = &_coroutine.promise();
36                }
37                char await_resume() noexcept {
38                        assert(_promise);
39                        return _promise->_value;
40                }
41        };
42
43        std::experimental::coroutine_handle<promise_type> _coroutine = nullptr;
44
45        explicit fmt_cor(std::experimental::coroutine_handle<promise_type> coroutine)
46                : _coroutine(coroutine)
47        {}
48
49        ~fmt_cor() {
50                if(_coroutine) {
51                        _coroutine.destroy();
52                        if (_coroutine.promise()._l->g != 0 | _coroutine.promise()._l->b != 0) {
53                                std::cout << "\n";
54                        }
55                }
56        }
57
58        fmt_cor() = default;
59        fmt_cor(fmt_cor const &) = delete;
60        fmt_cor& operator=(fmt_cor const &) = delete;
61
62        fmt_cor(fmt_cor&& other) {
63                std::swap(_coroutine, other._coroutine);
64        }
65
66        fmt_cor& operator=(fmt_cor&& other) {
67                if(&other != this) {
68                        _coroutine = other._coroutine;
69                        other._coroutine = nullptr;
70                }
71                return *this;
72        }
73
74        void send(char a) {
75                _coroutine.promise()._value = a;
76                _coroutine.resume();
77        }
78};
79
80fmt_cor Fmt() {
81        fmt_cor::promise_type::locals l;
82        co_yield l;
83        for(;;) {
84                for(l.g = 0; l.g < 5; l.g++) {
85                        for(l.b = 0; l.b < 4; l.b++) {
86                                std::cout << co_await fmt_cor::get();
87                        }
88                        std::cout << "  ";
89                }
90                std::cout << std::endl;
91        }
92}
93
94int main() {
95        auto fmt = Fmt();
96        for(int i = 0; i < 41; i++) {
97                fmt.send('a');
98        }
99}
Note: See TracBrowser for help on using the repository browser.