libcopp 2.3.2
Loading...
Searching...
No Matches
sample_readme_13.cpp
Go to the documentation of this file.
1// Copyright 2026 owent
2// Sample code for stackful coroutine channel/receiver model
3
6#include <libcotask/task.h>
7
8#include <cstdio>
9#include <iostream>
10#include <memory>
11
12// ===============================================
13// Example 1: Basic Channel Usage with cotask::task
14// ===============================================
15
16class producer_action : public cotask::impl::task_action_impl {
17 public:
18 producer_action(copp::stackful_channel_sender<int> sender) : sender_(std::move(sender)), value_to_send_(0) {}
19
20 int operator()(void*) override {
21 std::cout << "[Producer] Starting production..." << std::endl;
22
23 // Simulate producing values
24 for (int i = 1; i <= 5; ++i) {
25 value_to_send_ = i * 100;
26 std::cout << "[Producer] Producing value: " << value_to_send_ << std::endl;
27
28 // Send value through channel
29 sender_.set_value(value_to_send_);
30
31 std::cout << "[Producer] Value sent, yielding..." << std::endl;
32 }
33
34 std::cout << "[Producer] Production complete!" << std::endl;
35 return 0;
36 }
37
38 private:
39 copp::stackful_channel_sender<int> sender_;
41};
42
43class consumer_action : public cotask::impl::task_action_impl {
44 public:
45 consumer_action(copp::stackful_channel_receiver<int> receiver) : receiver_(std::move(receiver)) {}
46
47 int operator()(void*) override {
48 std::cout << "[Consumer] Starting consumption..." << std::endl;
49
50 // Receive values from channel
51 for (int i = 1; i <= 5; ++i) {
52 std::cout << "[Consumer] Waiting for value " << i << "..." << std::endl;
53
54 // await_value will suspend the task until a value is available
55 int value = cotask::task<>::this_task()->await_value(receiver_);
56
57 std::cout << "[Consumer] Received value: " << value << std::endl;
58
59 // Reset channel for next value
60 receiver_.reset_value();
61 }
62
63 std::cout << "[Consumer] Consumption complete!" << std::endl;
64 return 0;
65 }
66
67 private:
68 copp::stackful_channel_receiver<int> receiver_;
69};
70
72 std::cout << "\n========== Example 1: Basic Channel Usage ==========\n" << std::endl;
73
74 // Create a channel for int communication
75 std::pair<copp::stackful_channel_receiver<int>, copp::stackful_channel_sender<int>> channel =
76 copp::make_stackful_channel<int>();
77 auto receiver = std::move(channel.first);
78 auto sender = std::move(channel.second);
79
80 // Create consumer and producer tasks
81 auto consumer = cotask::task<>::create(consumer_action(std::move(receiver)));
82 auto producer = cotask::task<>::create(producer_action(std::move(sender)));
83
84 // Start consumer (it will suspend immediately waiting for data)
85 std::cout << "Starting consumer task..." << std::endl;
86 consumer->start();
87
88 std::cout << "\nStarting producer task..." << std::endl;
89 producer->start();
90
91 std::cout << "\nBoth tasks completed!" << std::endl;
92}
93
94// ===============================================
95// Example 2: Error Handling with Custom Transform
96// ===============================================
97
98class consumer_with_error_handling : public cotask::impl::task_action_impl {
99 public:
100 consumer_with_error_handling(copp::stackful_channel_receiver<int> receiver) : receiver_(std::move(receiver)) {}
101
102 int operator()(void*) override {
103 std::cout << "[Consumer] Starting with error handling..." << std::endl;
104
105 // First receive with default error handling
106 {
107 int value = cotask::task<>::this_task()->await_value(receiver_);
108 std::cout << "[Consumer] Received: " << value << std::endl;
109 receiver_.reset_value();
110 }
111
112 // Second receive with custom error transform
113 {
114 auto error_transform = [](copp::copp_error_code err) {
115 std::cout << "[Consumer] Error occurred: " << static_cast<int>(err) << ", returning default value -1"
116 << std::endl;
117 return -1; // Return default value on error
118 };
119
120 int value = cotask::task<>::this_task()->await_value(receiver_, error_transform);
121 std::cout << "[Consumer] Received or defaulted: " << value << std::endl;
122 }
123
124 return 0;
125 }
126
127 private:
128 copp::stackful_channel_receiver<int> receiver_;
129};
130
132 std::cout << "\n========== Example 2: Error Handling ==========\n" << std::endl;
133
134 std::pair<copp::stackful_channel_receiver<int>, copp::stackful_channel_sender<int>> channel =
135 copp::make_stackful_channel<int>();
136 auto receiver = std::move(channel.first);
137 auto sender = std::move(channel.second);
138
139 auto consumer = cotask::task<>::create(consumer_with_error_handling(std::move(receiver)));
140
141 consumer->start();
142
143 // Send first value normally
144 sender.set_value(42);
145
146 // Kill the consumer task to trigger error handling
147 std::cout << "\nKilling consumer task to demonstrate error handling..." << std::endl;
148 consumer->kill();
149
150 std::cout << "\nTask killed!" << std::endl;
151}
152
153// ===============================================
154// Example 3: Using with copp::coroutine_context directly
155// ===============================================
156
158 copp::stackful_channel_receiver<int> receiver;
160};
161
162int direct_consumer_runner(void* data_ptr) {
163 auto* data = static_cast<direct_context_example_data*>(data_ptr);
164
165 std::cout << "[Direct Consumer] Starting..." << std::endl;
166
167 // Use inject_await with error transform for low-level control
168 auto error_transform = [](copp::copp_error_code err) {
169 std::cout << "[Direct Consumer] Error: " << static_cast<int>(err) << std::endl;
170 return 0;
171 };
172
173 for (int i = 0; i < 3; ++i) {
174 // Get current coroutine context
175 auto* ctx = copp::this_coroutine::get<copp::coroutine_context>();
176
177 std::cout << "[Direct Consumer] Awaiting value " << (i + 1) << "..." << std::endl;
178
179 // Directly use inject_await on receiver
180 int value = data->receiver.inject_await(ctx, error_transform);
181
182 std::cout << "[Direct Consumer] Received: " << value << std::endl;
183 data->received_sum += value;
184
185 data->receiver.reset_value();
186 }
187
188 std::cout << "[Direct Consumer] Total sum: " << data->received_sum << std::endl;
189 return 0;
190}
191
193 std::cout << "\n========== Example 4: Direct Coroutine Context Usage ==========\n" << std::endl;
194
195 std::pair<copp::stackful_channel_receiver<int>, copp::stackful_channel_sender<int>> channel =
196 copp::make_stackful_channel<int>();
197 auto receiver = std::move(channel.first);
198 auto sender = std::move(channel.second);
199
201 data.receiver = std::move(receiver);
202
203 // Create coroutine context directly
204 typedef copp::coroutine_context_container<copp::allocator::stack_allocator_malloc> coroutine_t;
205
206 coroutine_t::ptr_t co = coroutine_t::create(direct_consumer_runner);
207
208 std::cout << "Starting direct coroutine..." << std::endl;
209 co->start(&data);
210
211 // Send values
212 for (int value : {10, 20, 30}) {
213 std::cout << "\nSending value: " << value << std::endl;
214 sender.set_value(value);
215 }
216
217 std::cout << "\nDirect coroutine completed with sum: " << data.received_sum << std::endl;
218}
219
220// ===============================================
221// Main
222// ===============================================
223
224int main() {
225#if defined(LIBCOTASK_MACRO_ENABLED)
229
230 std::cout << "\n========== All Examples Completed! ==========\n" << std::endl;
231#else
232 std::cerr << "libcotask is not enabled, sample is disabled" << std::endl;
233#endif
234 return 0;
235}
consumer_action(copp::stackful_channel_receiver< int > receiver)
int operator()(void *) override
copp::stackful_channel_receiver< int > receiver_
consumer_with_error_handling(copp::stackful_channel_receiver< int > receiver)
copp::stackful_channel_receiver< int > receiver_
int operator()(void *) override
producer_action(copp::stackful_channel_sender< int > sender)
copp::stackful_channel_sender< int > sender_
STL namespace.
int direct_consumer_runner(void *data_ptr)
void example_basic_channel()
int main()
void example_error_handling()
void example_direct_coroutine_context()
copp::stackful_channel_receiver< int > receiver