Bienvenidos sean a este post, hoy veremos una mecanica que nos puede ayudar.
En los ultimos posts hemos visto distintas maneras de poder manejar threads. Tambien pudimos ver como trabaja donde al margen de crear un nuevo thread, estos van alternando entre ellos pausando y retomando de momentos si el numero de threads excede los limites establecidos por el hardware. Mas alla de esto, la creacion de los threads tambien nos consume recursos en el PC, y por esta razon una de las practicas sugeridas para cuando tenemos muchos threads es la utilizacion de una pool de threads. La idea detras de esto esta basado en caching. Para ello se crean y mantienen threads en un contenedor para ser usados luego. Veamos el siguiente ejemplo:
std::vector<std::thread> pool;
Este vector contendra objetos de tipo thread, con esto si necesitamos nuevos threads no es necesario crear uno nuevo sino que usaremos uno de los que estan almacenados en el pool. Esto permite que una vez finalizado el uso simplemente lo mandamos nuevamente al pool y lo podemos volver a usar en caso de ser necesario. Un ejemplo de como usar un pool de threads lo vimos en este post.
Otro ejemplo puede ser un servidor web, este programa espera por clientes entrantes y crea una conexion separada para cada cliente para ser procesadas independientemente de los otros. Sabemos que un tipico servidor web maneja cientos de conexiones al mismo tiempo. Esto implica que cada vez que se realiza una nueva conexion, el servidor crea un nuevo thread y manejar las solicitudes del cliente. Veamos el siguiente posible ejemplo:
void process_incoming_connections() {
if (nueva conexion del cliente) {
t = crear_thread();
t.manejar_requests(cliente);
}
}
while (true) {
process_incoming_connections();
}
Es un codigo simple donde por cada conexion nueva creara un nuevo thread, si tenemos un pool de threads este sera asignnado a uno interno. Como comentamos anteriormente, cada vez que se crea un thread esto tiene un costo porque utiliza recursos y tiempos del S.O y esto al evitar que se cree uno nuevo cada vez que se necesita nos ahorra tiempo. Pero esto se puede mejorar aun mas, simplemente reemplazando al vector por un queue. Esto hara que cada vez que solicitemos un thread, el pool devolvera un thread libre y cuando hayas terminado lo devolvera a pool. Veamos un ejemplo simple de como puede ser un pool de threads:
class PoolThread
{
public:
PoolThread(int num_de_threads = 1000) {
for (int ix = 0; ix < num_de_threads; ++ix) {
pool_.push(std::thread());
}
}
std::thread get_thread_libres() {
if (pool_.empty()) {
throw std::exception("no hay thread disponibles");
}
auto t = pool_.front();
pool_.pop();
return t;
}
void push_thread(std::thread t) {
pool_.push(t);
}
private:
std::queue<std::thread> pool_;
};
En la parte privada se genera el pool que contendra a los threads. En la parte privada lo administraremos, comencemos con el constructor. Este creara los threads en el pool, si no informamos la cantidad de manera predeterminada creara 1000. Observen que simplemente agregamos threads vacios mediante push en el queue. El siguiente metodo lo usamos para obtener un thread libre. Para esto usamos a front y este lo asignamos a un objeto, para luego liberar el thread que se encuentre en pool_ y finalmente devolver el thread que obtuvimos. Y el ultimo metodo sera para asignar el thread recibido al elemento actual en el pool. Para aplicarlo, tomemos nuevamente el codigo de las conexiones y hagamos el siguiente cambio:
PoolThread pool;
void process_incoming_connections() {
if (nueva conexion del cliente) {
t = pool.get_thread_libres();
t.manejar_requests(cliente);
}
}
while (true) {
process_incoming_connections();
}
Primero creamos un objeto de la clase encargada del pool, luego quitamos a la funcion que teniamos para crear los threads y la reemplazamos por el metodo encargado de conseguir los thread libres del pool. Y asumiremos que ahora la funcion encargada de manejar los requests, una vez que finalizo todo procede a liberar el thread y lo devuelve al pool. Si bien esto en produccion seria completamente inutil, nos da una idea basica de como se comporta uno de verdad.
En resumen, hoy hemos visto pool de thread de forma basica, en que nos beneficia, como se comporta, como se accede y como se devuelve, asi como algunas pequeñas variantes que pueden beneficiarnos. Espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donation
It’s for maintenance of the site, thanks!
$1.50
