coroutine (tsz. coroutines)
coroutines
) C++-ban olyan speciális függvények, amelyek végrehajtása megszakítható és folytatható. Hatékonyabbá teszik az aszinkron programozást, mivel lehetővé teszik a függvények szüneteltetését és folytatását anélkül, hogy blokkolnák a teljes programot.A C++20 bevezette a korutinok támogatását, amely három új kulcsszóval működik: - co_await
– Egy várakozó művelet végrehajtása. - co_yield
– Egy érték visszaadása és a végrehajtás szüneteltetése. - co_return
– Egy érték visszaadása és a korutin befejezése.
A hagyományos függvények futásukat a végrehajtás végéig folytatják, míg a korutinok szüneteltethetők és később folytathatók, így ideálisak például: ✔ Aszinkron műveletekhez (pl. fájlműveletek, hálózati hívások).
✔ Lusta kiértékeléshez (pl. folyamatosan számított adatsorok, iterátorok).
✔ Event-loop vagy task handlinghez.
co_yield
példányA co_yield
segítségével egy korutin értéket ad vissza, majd szünetelteti magát.
#include <iostream>
#include <coroutine>
// Generátor osztály definiálása
template<typename T>
struct Generator {
struct promise_type {
T current_value;
Generator get_return_object() { return Generator{this}; }
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
std::suspend_always yield_value(T value) {
current_value = value;
return {};
}
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
using handle_type = std::coroutine_handle<promise_type>;
handle_type coro;
explicit Generator(promise_type* p) : coro(handle_type::from_promise(*p)) {}
~Generator() { if (coro) coro.destroy(); }
bool next() {
if (!coro || coro.done()) return false;
coro.resume();
return !coro.done();
}
T value() { return coro.promise().current_value; }
};
// Korutin, amely számsorozatot generál
Generator<int> szamok(int start, int end) {
for (int i = start; i <= end; ++i)
co_yield i; // Visszaad egy számot, majd szünetel
}
int main() {
auto gen = szamok(1, 5);
while (gen.next()) {
std::cout << "Korutin által generált szám: " << gen.value() << std::endl;
}
return 0;
}
🔹 Mi történik itt? 1. A Generator<int>
egy olyan korutin, amely számokat ad vissza (co_yield
). 2. A szamok(1, 5)
egy 1-től 5-ig terjedő számokat generáló függvény. 3. Minden co_yield
híváskor egy értéket visszaad, majd szünetel. 4. A next()
metódussal folytathatjuk a korutin végrehajtását.
co_await
– Aszinkron várakozás korutinnalA co_await
segítségével egy korutin várakozhat egy aszinkron művelet befejezésére anélkül, hogy blokkolná a programot.
#include <iostream>
#include <coroutine>
#include <chrono>
#include <thread>
// Egyszerű aszinkron várakozó típus
struct Awaiter {
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<> h) {
std::this_thread::sleep_for(std::chrono::seconds(2)); // 2 másodperc várakozás
h.resume(); // Korutin folytatása
}
void await_resume() {}
};
// Aszinkron korutin
struct Task {
struct promise_type {
Task get_return_object() { return {}; }
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
};
Task varj() {
std::cout << "Várakozás kezdete..." << std::endl;
co_await Awaiter(); // 2 másodperces aszinkron várakozás
std::cout << "Várakozás vége!" << std::endl;
}
int main() {
varj(); // Aszinkron hívás
std::cout << "A főprogram nem állt meg!" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3)); // A főprogram nem blokkolódik
return 0;
}
🔹 Mit csinál ez a kód? 1. A co_await
segítségével a korutin várakozik egy eseményre, de nem blokkolja a fő programot. 2. A Awaiter
egy egyszerű várakozási mechanizmust biztosít. 3. A főprogram nem áll le, hanem párhuzamosan fut a korutin várakozásával.
co_return
– Érték visszaadása korutinbólA co_return
segítségével egy korutin véglegesen visszaadhat egy értéket.
co_return
használata#include <iostream>
#include <coroutine>
// Egyszerű korutin, amely egy értéket ad vissza
struct Task {
struct promise_type {
int value;
Task get_return_object() { return Task{this}; }
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_value(int v) { value = v; }
void unhandled_exception() { std::terminate(); }
};
using handle_type = std::coroutine_handle<promise_type>;
handle_type coro;
explicit Task(promise_type* p) : coro(handle_type::from_promise(*p)) {}
~Task() { if (coro) coro.destroy(); }
int get() { return coro.promise().value; }
};
// Korutin függvény
Task korutin() {
co_return 42; // Visszaad egy értéket
}
int main() {
auto t = korutin();
std::cout << "Korutin visszatérési értéke: " << t.get() << std::endl;
return 0;
}
🔹 Mit csinál ez a kód? - A korutin egyetlen számot (42
) ad vissza co_return
segítségével. - A Task
osztály segítségével a get()
függvény visszakapja ezt az értéket.
✅ A korutinok (coroutines
) lehetővé teszik a függvények szüneteltetését és folytatását.
✅ co_yield
– Egy értéket ad vissza, majd szünetelteti a végrehajtást.
✅ co_await
– Várakoztatja a korutint aszinkron módon.
✅ co_return
– Véglegesen visszaad egy értéket.
✅ Használatuk segít az aszinkron programozásban, adatfolyamok kezelésében és optimalizálásban.