¿Cómo esperar a que cualquier operación asincrónica finalice y obtener su índice?
Necesito esperar por múltiples tareas asíncronas pero no quiero ningún comportamiento de bloqueo, así que revisé esta respuesta y creé un algoritmo asíncrono no bloqueante. Aquí está mi código:
std::vector<><int>> asyncs;
for (int i{0}; i < 4; i++) {
asyncs.push_back(std::async(
std::launch::async,
do_something) // do_something() espera durante una cantidad aleatoria de milisegundos y devuelve el tiempo esperado
);
}
for (auto&& fut:asyncs) {
std::cout << "Tiempo de espera: " << fut.get() << std::endl;
}
Entonces, cuando lo ejecuto, obtengo la siguiente salida:
Tiempo de espera: 1544
Tiempo de espera: 3350
Tiempo de espera: 2915
Tiempo de espera: 2775
Sin embargo, no sé en qué orden se iniciaron. ¿Se inició primero la async que se ejecutó durante 1544ms
o al último? ¿Se inició 2775ms
segundo o tercero? Antes de usar métodos no bloqueantes, haría:
for (int i{0}; i < 4; i++) int value = asyncs[i].get();
Esto me permitía saber exactamente qué tarea había terminado porque era ese índice en el vector. Estoy codificando para la velocidad, por lo que no quiero buscar en el vector cada vez que una async termina. Y no quiero hacer nada descuidado como enviar el índice como parámetro y devolver una tupla.
davy.ai
Como experto en TI especializado en C++, asíncrono y vector, puedes modificar el código de tareas asincrónicas no bloqueantes para conocer cuál tarea ha finalizado sin comportamiento de bloqueo. Una posible solución es usar un mapa para almacenar cada futuro junto con su índice correspondiente en el vector. Aquí hay un ejemplo de cómo se puede hacer:
Este código crea un mapa
future_index_map
que mapea cada futuro con su índice correspondiente en el vector. En el bucle que espera a que las tareas finalicen, primero verifica el estado de cada futuro con un tiempo de espera cero utilizandowait_for()
. Si un futuro está listo, recupera su índice del mapa y luego lo elimina del vector utilizandoerase()
. Finalmente, imprime el índice y el tiempo de espera.De esta manera, puede mantener el comportamiento no bloqueante del código y también saber qué tarea ha finalizado y su índice en el vector sin ningún paso adicional de parámetros o búsqueda.