Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Comunicaciones y Sistemas
ARQUITECTURA DE
COMPUTADORES
ISO C++ Threads
2 Hilos
Enfoque tradicional:
Bibliotecas de funciones.
Ligadas a una o pocas plataformas.
Baja portabilidad.
Ejemplos:
Pthreads, Windows Threads, …
int main() {
std::thread t(hola);
t.join();
return 0;
}
6 Un objeto llamable
8 join() y excepciones
class control_hilo {
private:
std::thread & t;
public:
explicit control_hilo(std::thread & h) : t(h) {}
~control_hilo() {
if (t.joinable()) { t.join(); }
}
control_hilo(control_hilo const &) = delete;
control_hilo & operator=(control_hilo&) = delete;
};
Arquitectura de Computadores - Curso 2011
10 join() y excepciones
void f() {
std::thread t(tarea);
control_hilo c(t);
otra_cosa();
Hilo se libera en destructor de
} objeto c
12 detach
14 Paso de parámetros
void h() {
int a=10;
double b=1.0;
string n=“hola”;
std::thread t1(f, a, b, n);
std::thread t2(g, std::ref(a), b, std::ref(n));
…
}
Arquitectura de Computadores - Curso 2011
15 Paso de parámetros
class X {
public:
void realizar_tarea();
…
};
int main() {
X a;
std::thread t(&X::realizar_tarea, &a);
t.join();
…
}
Arquitectura de Computadores - Curso 2011
18
std::thread f() {
return std::thread(tarea1);
}
std::thread g() {
std::thread t(tarea2, 100);
return t;
}
int main() {
std::thread t1 = std::move(f());
std::thread t2 = std::move(g());
…
}
class control_hilo {
private:
std::thread t; //Sin & t
public:
explicit control_hilo(std::thread & h) : t(std::move(h)) {
if (!t.joinable()) throw std::logic_error(“No hay hilo”);
}
~control_hilo() { t.join(); }
control_hilo(control_hilo const &) = delete;
control_hilo & operator=(control_hilo&) = delete;
};
Arquitectura de Computadores - Curso 2011
20 El nuevo control_hilo
void f() {
control_hilo c(std::thread(tarea));
otra_cosa();
}
void f(int n) {
std::vector<std::thread> hilos; //Vector vacío
for (int i=0;i<n;i++) {
hilos.push_back(std::thread(tarea, i));
}
for_each(hilos.begin(), hilos.end(), [](std::thread & t) {
t.join(); });
}
22 Mutex
Problema:
Facilidad de olvidar unlock().
Solución:
RAII: Resource Acquisition Is Initialization.
Clase lock_guard.
std::mutex mimtx; }
void agrega(int v) {
std::lock_guard<std::mutex>
guard(mimtx);
lista.push_back(v);
}
std::shared_ptr<T> pop() {
std::lock_guard<std::mutex> milock(m);
if (p.empty()) throw logic_error(“Pila vacía”);
std::share_ptr<T> const r(std::make_shared<T>(data.top()));
data.pop();
return r;
}
mutex.
No recursivo.
Semántica de propiedad exclusiva.
recursive_mutex.
Recursivo: El hilo que tiene adquirido un mutex puede volver a
adquirirlo.
Semántica de propiedad exclusiva.
timed_mutex.
No recursivo.
Semántica de propiedad exclusiva.
Especificación de tiempo máximo (try_lock_for/try_lock_until).
recursive_timed_mutex.
Recursivo.
Semántica de propiedad exclusiva.
Especificación de tiempo máximo (try_lock_for/try_lock_until).
28 Variables condición
condition_variable.
Primitivas de sincronización para bloquear un hilo hasta
que otro hilo envíe una notificación.
Notificación:
notify_one()
notify_all()
30 Productor/Consumidor (Alternativa)
#include <future>
#include <iostream>
int main() {
std::future<int> r = std::async(tarea, 1, 10);
otra_tarea();
std::cout << “Resultado= “ << r.get() << std::endl;
return 0;
}
36 Tareas y futuros
std::packaged_task<>
Asocia la llamada a una función con un resultado.
Permite pasar tareas a hilos y recuperar después el
resultado.
std::packaged_task<int(int,int)> tarea;
Encapsula una función que toma dos enteros
void operator()(int,int)
Permite obtener el resultado en un futuro.
std::future<int> get_future()
38 Promesas
promise<R>
Es el vehículo para pasar un valor de retorno (o una
excepción) entre dos hilos.
Es una abstracción de paso de mensajes entre hilos.
Envío de mensaje:
set_value
set_exception
Recepción de mensaje:
Consulta del futuro asociado.
…
promise<int> p;
void func(promise<int> p) { unique_future<int> f =
int r; p.get_future();
try { std::thread t(func, std::move(p));
r = calcular_valor(); hacer_algo();
p.set_value(r) int r = f.get();
} …
catch (…) {
p.set_exception( std::curent_exception());
}
}