Skip to content

Commit 35f5fc7

Browse files
Copilotcaixuf
andcommitted
Add advanced coroutine features: yield, work-stealing, cache-aligned allocator
Co-authored-by: caixuf <130882544+caixuf@users.noreply.github.com>
1 parent 3bd4a84 commit 35f5fc7

5 files changed

Lines changed: 266 additions & 0 deletions

File tree

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* @file advanced_features_demo.cpp
3+
* @brief 演示FlowCoro的高级架构特性
4+
*/
5+
6+
#include <flowcoro.hpp>
7+
#include <iostream>
8+
9+
using namespace flowcoro;
10+
11+
// 演示1:使用yield进行协作式调度
12+
Task<int> cooperative_task(int id) {
13+
int result = 0;
14+
for (int i = 0; i < 1000; ++i) {
15+
result += i;
16+
17+
// 每100次迭代yield一次,让其他协程有机会执行
18+
if (i % 100 == 0) {
19+
co_await yield(); // 轻量级yield,不需要完整的重新调度
20+
}
21+
}
22+
co_return result;
23+
}
24+
25+
// 演示2:批量处理与周期性yield
26+
Task<void> batch_processing_task() {
27+
std::vector<int> data(10000);
28+
size_t counter = 0;
29+
30+
for (size_t i = 0; i < data.size(); ++i) {
31+
data[i] = i * 2;
32+
33+
// 使用BatchYieldAwaiter自动管理yield频率
34+
co_await BatchYieldAwaiter(counter, 500);
35+
}
36+
37+
std::cout << "Batch processing completed with " << counter << " yields\n";
38+
}
39+
40+
// 演示3:高性能并发任务
41+
Task<void> concurrent_workers() {
42+
std::vector<Task<int>> workers;
43+
44+
// 创建多个协作式工作任务
45+
for (int i = 0; i < 10; ++i) {
46+
workers.push_back(cooperative_task(i));
47+
}
48+
49+
// 等待所有任务完成
50+
int total = 0;
51+
for (auto& worker : workers) {
52+
total += co_await worker;
53+
}
54+
55+
std::cout << "Total result from " << workers.size() << " workers: " << total << "\n";
56+
}
57+
58+
// 演示4:立即执行的void任务(利用suspend_never)
59+
Task<void> immediate_void_task() {
60+
// 这个任务会立即执行,因为Task<void>现在使用suspend_never
61+
std::cout << "Immediate void task executing!\n";
62+
co_return;
63+
}
64+
65+
// 演示5:组合使用不同的异步原语
66+
Task<void> combined_async_operations() {
67+
std::cout << "Starting combined operations...\n";
68+
69+
// 1. 立即执行的任务
70+
co_await immediate_void_task();
71+
72+
// 2. 协作式yield
73+
co_await yield();
74+
75+
// 3. 延时操作
76+
co_await sleep_for(std::chrono::milliseconds(10));
77+
78+
// 4. 并发任务
79+
auto task1 = cooperative_task(1);
80+
auto task2 = cooperative_task(2);
81+
82+
auto [value, index] = co_await when_any(std::move(task1), std::move(task2));
83+
std::cout << "First completed task (index " << index << ") returned: " << value << "\n";
84+
85+
std::cout << "Combined operations completed!\n";
86+
}
87+
88+
int main() {
89+
std::cout << "=== FlowCoro Advanced Features Demo ===\n\n";
90+
91+
try {
92+
// 演示1: 协作式任务
93+
std::cout << "Demo 1: Cooperative Task\n";
94+
auto result1 = sync_wait(cooperative_task(0));
95+
std::cout << "Result: " << result1 << "\n\n";
96+
97+
// 演示2: 批量处理
98+
std::cout << "Demo 2: Batch Processing\n";
99+
sync_wait(batch_processing_task());
100+
std::cout << "\n";
101+
102+
// 演示3: 并发工作器
103+
std::cout << "Demo 3: Concurrent Workers\n";
104+
sync_wait(concurrent_workers());
105+
std::cout << "\n";
106+
107+
// 演示4: 立即执行的void任务
108+
std::cout << "Demo 4: Immediate Void Task\n";
109+
sync_wait(immediate_void_task());
110+
std::cout << "\n";
111+
112+
// 演示5: 组合操作
113+
std::cout << "Demo 5: Combined Async Operations\n";
114+
sync_wait(combined_async_operations());
115+
std::cout << "\n";
116+
117+
std::cout << "=== All demos completed successfully! ===\n";
118+
119+
} catch (const std::exception& e) {
120+
std::cerr << "Exception: " << e.what() << "\n";
121+
return 1;
122+
}
123+
124+
return 0;
125+
}

include/flowcoro.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
#include "flowcoro/simple_db.h"
5050
#include "flowcoro/rpc.h"
5151
#include "flowcoro/channel.h"
52+
#include "flowcoro/yield.h" // 新增:轻量级yield支持
53+
#include "flowcoro/task_allocator.h" // 新增:缓存友好的任务分配器
5254

5355
// #include "flowcoro/rpc.h" // 暂时注释掉复杂的RPC实现
5456

include/flowcoro/task_allocator.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#pragma once
2+
#include <memory>
3+
#include <new>
4+
#include <cstddef>
5+
6+
namespace flowcoro {
7+
8+
// 缓存对齐的协程promise分配器
9+
// 提高缓存局部性,减少false sharing
10+
template<typename T>
11+
class CacheAlignedAllocator {
12+
public:
13+
using value_type = T;
14+
using size_type = std::size_t;
15+
using difference_type = std::ptrdiff_t;
16+
17+
// C++20 alignas支持
18+
static constexpr size_t alignment = std::hardware_destructive_interference_size;
19+
20+
CacheAlignedAllocator() noexcept = default;
21+
22+
template<typename U>
23+
CacheAlignedAllocator(const CacheAlignedAllocator<U>&) noexcept {}
24+
25+
T* allocate(size_t n) {
26+
if (n == 0) return nullptr;
27+
28+
size_t size = n * sizeof(T);
29+
// 对齐到缓存行
30+
void* ptr = ::operator new(size, std::align_val_t{alignment});
31+
32+
if (!ptr) {
33+
throw std::bad_alloc();
34+
}
35+
36+
return static_cast<T*>(ptr);
37+
}
38+
39+
void deallocate(T* ptr, size_t) noexcept {
40+
::operator delete(ptr, std::align_val_t{alignment});
41+
}
42+
43+
template<typename U>
44+
bool operator==(const CacheAlignedAllocator<U>&) const noexcept {
45+
return true;
46+
}
47+
48+
template<typename U>
49+
bool operator!=(const CacheAlignedAllocator<U>&) const noexcept {
50+
return false;
51+
}
52+
};
53+
54+
// 为promise_type提供自定义分配器支持
55+
// 可以在promise_type中添加以下方法来使用:
56+
// void* operator new(std::size_t size) {
57+
// CacheAlignedAllocator<promise_type> alloc;
58+
// return alloc.allocate(1);
59+
// }
60+
//
61+
// void operator delete(void* ptr) noexcept {
62+
// CacheAlignedAllocator<promise_type> alloc;
63+
// alloc.deallocate(static_cast<promise_type*>(ptr), 1);
64+
// }
65+
66+
} // namespace flowcoro

include/flowcoro/yield.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#pragma once
2+
#include <coroutine>
3+
#include "coroutine_manager.h"
4+
5+
namespace flowcoro {
6+
7+
// 轻量级yield awaiter - 立即恢复,但给其他协程执行机会
8+
struct YieldAwaiter {
9+
bool await_ready() const noexcept {
10+
return false; // 总是挂起以给其他协程机会
11+
}
12+
13+
void await_suspend(std::coroutine_handle<> h) noexcept {
14+
// 立即重新调度当前协程,但允许其他协程先执行
15+
auto& manager = CoroutineManager::get_instance();
16+
manager.schedule_resume(h);
17+
}
18+
19+
void await_resume() const noexcept {}
20+
};
21+
22+
// 便捷函数:让出执行权
23+
inline YieldAwaiter yield() noexcept {
24+
return {};
25+
}
26+
27+
// 优化的批量操作awaiter - 在循环中周期性yield
28+
class BatchYieldAwaiter {
29+
private:
30+
size_t& counter_;
31+
const size_t yield_interval_;
32+
33+
public:
34+
BatchYieldAwaiter(size_t& counter, size_t yield_interval = 100)
35+
: counter_(counter), yield_interval_(yield_interval) {}
36+
37+
bool await_ready() const noexcept {
38+
// 只在达到间隔时才挂起
39+
return (++counter_ % yield_interval_) != 0;
40+
}
41+
42+
void await_suspend(std::coroutine_handle<> h) noexcept {
43+
auto& manager = CoroutineManager::get_instance();
44+
manager.schedule_resume(h);
45+
}
46+
47+
void await_resume() const noexcept {}
48+
};
49+
50+
} // namespace flowcoro

src/coroutine_pool.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,29 @@ class CoroutineScheduler {
250250
return queue_size_.load(std::memory_order_relaxed);
251251
}
252252

253+
// 工作窃取:尝试从队列中获取一批任务给其他调度器
254+
size_t try_steal_work(std::vector<std::coroutine_handle<>>& stolen_tasks, size_t max_steal = 32) {
255+
if (queue_size_.load(std::memory_order_relaxed) <= 1) {
256+
return 0; // 队列太小,不值得窃取
257+
}
258+
259+
size_t stolen_count = 0;
260+
std::coroutine_handle<> handle;
261+
262+
// 窃取一半的任务(最多max_steal个)
263+
size_t target_steal = std::min(queue_size_.load() / 2, max_steal);
264+
265+
while (stolen_count < target_steal && coroutine_queue_.dequeue(handle)) {
266+
if (handle && !handle.done()) {
267+
stolen_tasks.push_back(handle);
268+
stolen_count++;
269+
queue_size_.fetch_sub(1, std::memory_order_relaxed);
270+
}
271+
}
272+
273+
return stolen_count;
274+
}
275+
253276
size_t get_total_coroutines() const { return total_coroutines_.load(); }
254277
size_t get_completed_coroutines() const { return completed_coroutines_.load(); }
255278
size_t get_scheduler_id() const { return scheduler_id_; }

0 commit comments

Comments
 (0)