source: doc/papers/concurrency/examples/ProdCons.cpp@ 5b993e0

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 5b993e0 was 709e0e0, checked in by tdelisle <tdelisle@…>, 7 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.