source: doc/papers/concurrency/examples/ProdCons.cpp @ 709e0e0

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

Added C++20 ProdCons? example draft: It does not work, might be impossible

  • Property mode set to 100644
File size: 4.6 KB
Line 
1#include <cassert>
2#include <cstdlib>
3#include <iostream>
4#include <experimental/coroutine>
5#include <unistd.h>
6
7int random(int max) {
8        return std::rand() % max;
9}
10
11struct Prod;
12struct Cons;
13
14struct Prod {
15        struct local {
16                Cons * c;
17                int N, money, receipt;
18        };
19
20        struct promise_type {
21                local _l;
22
23                Prod get_return_object() {
24                        return Prod(std::experimental::coroutine_handle<promise_type>::from_promise(*this));
25                }
26
27                auto initial_suspend() { return std::experimental::suspend_never(); }
28                auto final_suspend()   { return std::experimental::suspend_always(); }
29
30                void return_void() {}
31                void unhandled_exception() {}
32        };
33
34        struct data {
35                promise_type * _promise = nullptr;
36                bool await_ready() noexcept { return false; }
37                void await_suspend(std::experimental::coroutine_handle<promise_type> _coroutine) noexcept {
38                        _promise = &_coroutine.promise();
39                }
40                local & await_resume() noexcept { assert(_promise); return _promise->_l; }
41        };
42
43        std::experimental::coroutine_handle<promise_type> _coroutine = nullptr;
44
45        explicit Prod(std::experimental::coroutine_handle<promise_type> coroutine)
46                : _coroutine(coroutine)
47        {}
48
49        ~Prod() {
50                if(_coroutine) { _coroutine.destroy(); }
51        }
52
53        Prod() = default;
54        Prod(Prod const &) = delete;
55        Prod& operator=(Prod const &) = delete;
56
57        Prod(Prod&& other) {
58                std::swap(_coroutine, other._coroutine);
59        }
60
61        Prod& operator=(Prod&& other) {
62                if(&other != this) {
63                        _coroutine = other._coroutine;
64                        other._coroutine = nullptr;
65                }
66                return *this;
67        }
68
69        static Prod main();
70
71        auto payment(int money) {
72                _coroutine.promise()._l.money = money;
73                struct ret {
74                        int _receipt;
75                        bool await_ready() { return false; }
76                        void await_suspend(std::experimental::coroutine_handle<>) {}
77                        int await_resume() { return _receipt; }
78                };
79                return ret{ _coroutine.promise()._l.receipt };
80        }
81
82        auto start(int N, Cons & c) {
83                _coroutine.promise()._l.c = &c;
84                _coroutine.promise()._l.N = N;
85                _coroutine.promise()._l.receipt = 0;
86                _coroutine.resume();
87        }
88};
89
90struct Cons {
91        struct local {
92                Prod * p;
93                int p1, p2, status;
94                bool done;
95        };
96
97        struct promise_type {
98                local _l;
99
100                Cons get_return_object() {
101                        return Cons(std::experimental::coroutine_handle<promise_type>::from_promise(*this));
102                }
103
104                auto initial_suspend() { return std::experimental::suspend_never(); }
105                auto final_suspend()   { return std::experimental::suspend_always(); }
106
107                void return_void() {}
108                void unhandled_exception() {}
109        };
110
111        struct data {
112                Prod * _p;
113                data(Prod & prod) : _p(&prod) {}
114                promise_type * _promise = nullptr;
115                bool await_ready() noexcept { return false; }
116                void await_suspend(std::experimental::coroutine_handle<promise_type> _coroutine) noexcept {
117                        _promise = &_coroutine.promise();
118                }
119                local & await_resume() noexcept { assert(_promise); _promise->_l.p = _p; return _promise->_l; }
120        };
121
122        std::experimental::coroutine_handle<promise_type> _coroutine = nullptr;
123
124        explicit Cons(std::experimental::coroutine_handle<promise_type> coroutine)
125                : _coroutine(coroutine)
126        {}
127
128        ~Cons() {
129                if(_coroutine) { _coroutine.destroy(); }
130        }
131
132        Cons() = default;
133        Cons(Cons const &) = delete;
134        Cons& operator=(Cons const &) = delete;
135
136        Cons(Cons&& other) {
137                std::swap(_coroutine, other._coroutine);
138        }
139
140        Cons& operator=(Cons&& other) {
141                if(&other != this) {
142                        _coroutine = other._coroutine;
143                        other._coroutine = nullptr;
144                }
145                return *this;
146        }
147
148        static Cons main( Prod & prod );
149
150        auto deliver(int p1, int p2) {
151                _coroutine.promise()._l.p1 = p1;
152                _coroutine.promise()._l.p2 = p2;
153
154                struct ret {
155                        int _status;
156                        bool await_ready() { return false; }
157                        void await_suspend(std::experimental::coroutine_handle<>) {}
158                        int await_resume() { return _status; }
159                };
160                return ret{ _coroutine.promise()._l.status };
161        }
162
163        auto stop() {
164                _coroutine.promise()._l.done = true;
165                struct ret {
166                        bool await_ready() { return false; }
167                        void await_suspend(std::experimental::coroutine_handle<>) {}
168                        void await_resume() {}
169                };
170                return ret{};
171        }
172};
173
174Prod Prod::main() {
175        auto & p = co_await Prod::data();
176        for(int i = 0; i < p.N; i++) {
177                int p1 = random(100), p2 = random(100);
178                std::cout << p1 << " " << p2;
179                int status = co_await p.c->deliver(p1, p2);
180                std::cout << " $" << p.money << std::endl << status;
181                p.receipt += 1;
182        }
183        co_await p.c->stop();
184        std::cout << "prod stops";
185}
186
187Cons Cons::main( Prod & prod ) {
188        auto & c = co_await Cons::data( prod );
189        int money = 1, receipt;
190        for(;!c.done ;) {
191                std::cout << c.p1 << " " << c.p2 << std::endl << " $" << money;
192                c.status += 1;
193                receipt = co_await c.p->payment( money );
194                std::cout << " #" << receipt;
195                money += 1;
196        }
197        std::cout << "const stops";
198}
199
200int main() {
201        auto prod = Prod::main();
202        auto cons = Cons::main( prod );
203        srandom( getpid() );
204        prod.start(5, cons);
205}
Note: See TracBrowser for help on using the repository browser.