Khái niệm cơ bản về Coroutine
Coroutine là một dạng mở rộng của hàm và thủ tục, cho phép tạm dừng và tiếp tục thực thi tại bất kỳ thời điểm nào. Khác với hàm truyền thống, coroutine có thể:
- Dừng lại (suspend) khi gặp điều kiện nhất định
- Tiếp tục thực thi (resume) sau khi được kích hoạt lại
Các ứng dụng phổ biến của coroutine bao gồm:
- Tạo generator để sinh dữ liệu tuần tự
- Xử lý các hàm bất đồng bộ (asynchronous)
Triển khai với boost::coroutines2::coroutine
Thư viện Boost cung cấp lớp coroutine để xây dựng coroutine với hai kiểu chính là pull_type và push_type. Kiểu pull_type dùng để nhận dữ liệu từ push_type, ngược lại push_type dùng để gửi dữ liệu đến pull_type.
#include <iostream>
#include <boost/coroutine2/coroutine.hpp>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
typedef boost::coroutines2::coroutine<int> coro_t;
int limit = 8;
coro_t::pull_type producer(
[&](coro_t::push_type& consumer){
int a = 1, b = 1;
consumer(a);
consumer(b);
for(int i = 0; i < limit; ++i){
int c = a + b;
a = b;
b = c;
consumer(c);
}
});
for(auto value: producer)
cout << value << " ";
cout << endl;
coro_t::push_type consumer(
[&](coro_t::pull_type& producer){
while(producer){
cout << producer.get() << " ";
producer();
}
});
vector<int> numbers{1,1,2,3,5,8,13,21,34,55};
copy(begin(numbers), end(numbers), begin(consumer));
}
So sánh với C#
Dưới đây là cách triển khai tương tự trong C#:
using System;
using System.Collections.Generic;
namespace CoroutineExample
{
class Program
{
static void Main(string[] args)
{
IEnumerable<int> GenerateSequence(int count)
{
int a = 1, b = 1;
yield return a;
yield return b;
for(int i = 0; i < count; ++i){
int c = a + b;
a = b;
b = c;
yield return c;
}
}
foreach(var value in GenerateSequence(8))
Console.Write($"{value} ");
Console.WriteLine();
var numbers = new List<int>{1,1,2,3,5,8,13,21,34,55};
void ProcessData()
{
foreach(var value in numbers)
Console.Write($"{value} ");
}
ProcessData();
}
}
}