12#if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
14template <
class TReceiver>
15static inline void reset_channel_value(TReceiver& receiver) {
16 auto ctx = receiver.get_context();
26copp::callable_future<int> basic_consumer(copp::generator_channel_receiver<int> receiver) {
27 std::cout <<
"[Consumer] Waiting for first value..." << std::endl;
30 int value1 =
co_await receiver;
31 std::cout <<
"[Consumer] Received first value: " << value1 << std::endl;
34 reset_channel_value(receiver);
36 std::cout <<
"[Consumer] Waiting for second value..." << std::endl;
37 int value2 =
co_await receiver;
38 std::cout <<
"[Consumer] Received second value: " << value2 << std::endl;
40 reset_channel_value(receiver);
42 std::cout <<
"[Consumer] Waiting for third value..." << std::endl;
43 int value3 =
co_await receiver;
44 std::cout <<
"[Consumer] Received third value: " << value3 << std::endl;
46 co_return value1 + value2 + value3;
50 std::cout <<
"\n========== Example 1: Basic C++20 Channel Usage ==========\n" << std::endl;
53 auto [receiver, sender] = copp::make_channel<int>();
56 std::cout <<
"Starting consumer coroutine..." << std::endl;
57 auto consumer_future = basic_consumer(std::move(receiver));
59 std::cout <<
"\nConsumer is now waiting for values..." << std::endl;
60 std::cout <<
"Is consumer ready? " << (consumer_future.is_ready() ?
"Yes" :
"No") << std::endl;
63 std::cout <<
"\nSending first value: 10" << std::endl;
64 sender->set_value(10);
66 std::cout <<
"\nSending second value: 20" << std::endl;
67 sender->set_value(20);
69 std::cout <<
"\nSending third value: 30" << std::endl;
70 sender->set_value(30);
72 std::cout <<
"\nConsumer completed with sum: " << consumer_future.get_internal_promise().data() << std::endl;
79copp::callable_future<void> producer_coroutine(copp::generator_channel_sender<int> sender,
int count) {
80 std::cout <<
"[Producer] Starting to produce " << count <<
" values..." << std::endl;
82 for (
int i = 1; i <= count; ++i) {
84 std::cout <<
"[Producer] Producing value " << i <<
": " << value << std::endl;
87 sender->set_value(value);
90 auto current_status =
co_yield copp::callable_future<void>::yield_status();
94 std::cout <<
"[Producer] Production complete!" << std::endl;
98copp::callable_future<int> consumer_coroutine(copp::generator_channel_receiver<int> receiver,
int count) {
99 std::cout <<
"[Consumer] Starting to consume " << count <<
" values..." << std::endl;
102 for (
int i = 1; i <= count; ++i) {
103 std::cout <<
"[Consumer] Waiting for value " << i <<
"..." << std::endl;
105 int value =
co_await receiver;
106 std::cout <<
"[Consumer] Received value " << i <<
": " << value << std::endl;
109 reset_channel_value(receiver);
112 std::cout <<
"[Consumer] Consumption complete! Total sum: " << sum << std::endl;
116void example_producer_consumer() {
117 std::cout <<
"\n========== Example 2: Producer/Consumer Pattern ==========\n" << std::endl;
119 auto [receiver, sender] = copp::make_channel<int>();
122 auto consumer = consumer_coroutine(std::move(receiver), 5);
123 auto producer = producer_coroutine(sender, 5);
125 std::cout <<
"\nBoth coroutines completed!" << std::endl;
126 std::cout <<
"Final sum: " << consumer.get_internal_promise().data() << std::endl;
133struct custom_error_transform {
134 int operator()(copp::promise_status status)
const {
135 if (status == copp::promise_status::kKilled) {
136 std::cout <<
"[Error Transform] Coroutine was killed, returning -999" << std::endl;
138 }
else if (status == copp::promise_status::kTimeout) {
139 std::cout <<
"[Error Transform] Timeout occurred, returning -888" << std::endl;
142 std::cout <<
"[Error Transform] Other error: " <<
static_cast<int>(status) <<
", returning -1" << std::endl;
148 copp::generator_channel_receiver<int, custom_error_transform> receiver) {
149 std::cout <<
"[Consumer] Waiting for value (with custom error handling)..." << std::endl;
152 int value =
co_await receiver;
154 std::cout <<
"[Consumer] Received value or error default: " << value << std::endl;
159 std::cout <<
"\n========== Example 3: Error Handling with Custom Transform ==========\n" << std::endl;
161 auto [receiver, sender] = copp::make_channel<int, custom_error_transform>();
165 std::cout <<
"\nKilling consumer to demonstrate error handling..." << std::endl;
166 consumer.kill(copp::promise_status::kKilled,
true);
168 std::cout <<
"Consumer result after kill: " << consumer.get_internal_promise().data() << std::endl;
175copp::callable_future<void> void_channel_consumer(copp::generator_channel_receiver<void> receiver) {
176 std::cout <<
"[Consumer] Waiting for signal 1..." << std::endl;
178 std::cout <<
"[Consumer] Received signal 1!" << std::endl;
180 reset_channel_value(receiver);
182 std::cout <<
"[Consumer] Waiting for signal 2..." << std::endl;
184 std::cout <<
"[Consumer] Received signal 2!" << std::endl;
186 reset_channel_value(receiver);
188 std::cout <<
"[Consumer] Waiting for signal 3..." << std::endl;
190 std::cout <<
"[Consumer] Received signal 3!" << std::endl;
195void example_void_channel() {
196 std::cout <<
"\n========== Example 4: Void Channel (Signaling) ==========\n" << std::endl;
198 auto [receiver, sender] = copp::make_channel<void>();
200 auto consumer = void_channel_consumer(std::move(receiver));
202 std::cout <<
"\nSending signal 1..." << std::endl;
205 std::cout <<
"\nSending signal 2..." << std::endl;
208 std::cout <<
"\nSending signal 3..." << std::endl;
211 std::cout <<
"\nConsumer completed!" << std::endl;
218void example_vtable_types() {
219 std::cout <<
"\n========== Example 5: Generator VTable Types ==========\n" << std::endl;
221 std::cout <<
"libcopp provides three generator vtable types:\n" << std::endl;
223 std::cout <<
"1. generator_vtable_type::kDefault" << std::endl;
224 std::cout <<
" - Uses std::function for callbacks (most flexible)" << std::endl;
225 std::cout <<
" - Can capture complex state in lambdas" << std::endl;
226 std::cout <<
" - Type: copp::generator_future<T>" << std::endl;
227 std::cout <<
" - Best for: Complex scenarios with stateful callbacks\n" << std::endl;
229 std::cout <<
"2. generator_vtable_type::kLightWeight" << std::endl;
230 std::cout <<
" - Uses function pointers instead of std::function" << std::endl;
231 std::cout <<
" - Lower overhead, faster performance" << std::endl;
232 std::cout <<
" - Type: copp::generator_lightweight_future<T>" << std::endl;
233 std::cout <<
" - Best for: Performance-critical code with simple callbacks\n" << std::endl;
235 std::cout <<
"3. generator_vtable_type::kNone" << std::endl;
236 std::cout <<
" - No callbacks, designed for channel/receiver pattern" << std::endl;
237 std::cout <<
" - Minimal overhead, most efficient" << std::endl;
238 std::cout <<
" - Type: copp::generator_channel_future<T> (used by make_channel)" << std::endl;
239 std::cout <<
" - Best for: Channel-based communication between coroutines\n" << std::endl;
241 std::cout <<
"Recommendation:" << std::endl;
242 std::cout <<
" - For channels: Use make_channel() (kNone vtable)" << std::endl;
243 std::cout <<
" - For simple futures: Use generator_lightweight_future (kLightWeight)" << std::endl;
244 std::cout <<
" - For complex futures: Use generator_future (kDefault)\n" << std::endl;
253 example_producer_consumer();
255 example_void_channel();
256 example_vtable_types();
258 std::cout <<
"\n========== All C++20 Channel Examples Completed! ==========\n" << std::endl;
265 std::cerr <<
"C++20 coroutine is not enabled, sample is disabled" << std::endl;
void example_basic_channel()
void example_error_handling()