Última actualización:2026-10-12
C++20 channel en la práctica¶
Channel en la práctica con C++20¶
Continuando con las dos sesiones en directo anteriores, donde explicamos el uso y la implementación subyacente de thread, jthread, stop_token, stop_source, stop_callback, cv, cv_any, etc., ¿cómo construir un pequeño proyecto a partir de esos conocimientos?
De ahí surge esta entrega: escribir un channel.
1.Diseño¶
1.1 Diseño de la interfaz¶
En cuanto a la interfaz, esperamos que sea como un channel genérico, capaz de crear de una sola vez un channel de envío y de recepción.
Por ejemplo:
La implementación puede ofrecer una interfaz hacia el exterior similar a la de make_unique, y el valor de retorno se obtiene mediante las vinculaciones estructuradas de C++17; con esto ya tenemos dos channel.
Las dos interfaces esenciales: enviar y recibir.
- Enviar
- Recibir
Además, se puede proporcionar una interfaz shutdown en el destructor, de modo que cuando send o recv estén bloqueados puedan despertarse y liberarse.
Por ejemplo:
bool shutdown() {
if (!state_) {
return false;
}
light_city_lock lk(state_->mutex);
if (source_.stop_requested()) {
return false;
}
source_.request_stop();
state_->cv.notify_all();
return true;
}
1.2 Diseño de la cola interna¶
Para la cola interna puede tomarse como referencia lo publicado hace unos días sobre cómo diseñar una cola thread-safe de múltiples productores y consumidores; aquí podemos mantener internamente un state, junto con queue, mutex y cv_any.
struct State {
std::queue<T> queue;
std::mutex mutex;
// C++11 condition_variable_any
std::condition_variable_any cv;
};
2.Uso¶
Su uso es muy sencillo: basta con hacer (make) dos channel y luego send y recv.
Aquí he usado jthread + stop_token para este trabajo, por ejemplo:
std::jthread sender_thread(
[](Channel<int> sender, std::stop_token token) {
int counter = 0;
while (!token.stop_requested()) {
sender.send(counter++);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
},
std::move(sender), token);
El hilo receptor es parecido; cuando la ejecución está a punto de terminar, podemos usar
Con esto queda simulado un channel: el extremo emisor envía datos y el extremo receptor los recibe.
Ejemplo de ejecución:
➜ channel ./a.out
Received: 0
Received: 1
Received: 2
Received: 3
Received: 4
Received: 5
Received: 6
Received: 7
Received: 8
Received: 9
Temas relacionados¶
- Introducción a las corrutinas de C++20 | C++那些事
- Conceptos Concepts de C++20 | C++那些事
- constexpr y la expresión coma en C++20 | C++那些事
- Orden de bytes endian en C++20 | C++那些事
- Expresiones lambda de C++20 (parte 1) | C++那些事
- Módulos Modules de C++20 | C++那些事
- La biblioteca Ranges de C++20 | C++那些事
- Diseño y trampas de std::span en C++20 | C++那些事
- Guía de las novedades de C++20 | C++那些事
- C++20 [[likely]] y [[unlikely]] | C++那些事