
std::async foi introduzido no C++11. Ele é um template de função que aceita funções de callback como argumento e potencialmente os executa de forma assíncrona.
Ou seja, utilizando-o você pode melhorar a velocidade de uma aplicação, pois o tempo de retorno é usado de forma paralela.
Podemos criar std::async com 3 políticas de inicialização diferentes:
std::launch::async - Ele garante o comportamento assíncrono, ou seja, a função passada será executada em uma thread separada.std::launch::deferred - Comportamento não assíncrono, a função será chamada quando outro thread chamar get() no futuro para acessar o estado compartilhado.std::launch::async | std::launch::deferred - É o comportamento padrão. Com esta política de inicialização, ele pode ser executado de forma assíncrona ou não.Se não especificarmos uma política de inicialização, std::launch::async | std::launch::deferred será utilizado.
No exemplo desse artigo vamos utilizar std::launch::async.
Podemos passar qualquer tipo de função de callback em std::async:
Suponhamos que estamos desenvolvendo uma aplicação que precisa consumir 2 APIs diferentes e os dados retornados dessas APIs precisamos concatenar com dados que possuímos para gerar um novo nome.
Sem usar std::async faríamos mais ou menos assim:
Vamos ustilizar std::chrono para criar um
sleeppara dar impressão que seria o tempo de demora do retorno dos dados.
std::async
vim exemplo-sem-async.cpp
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
// Obter os dados da 1º API, tem um tempo de 2 segundos
std::string get_first_data_api(std::string ret_data){
  // sleep de 2 segundos
  std::this_thread::sleep_for( std::chrono::seconds(2));
  return "FIRST_" + ret_data;
}
// Obter os dados da 2º API, tem também um tempo de 2 segundos
std::string get_second_data_api(std::string ret_data){
  // sleep de 2 segundos
  std::this_thread::sleep_for( std::chrono::seconds(2));
  return "SECOND_" + ret_data;
}
int main(){
  // Obtém o início do tempo para a contagem
  std::chrono::system_clock::time_point start = 
    std::chrono::system_clock::now();
  // Solicita os dados da primeira API
  std::string first_api = get_first_data_api("NUMERO_UM");
  // Solicita os dados da segunda API
  std::string second_api = get_second_data_api("NUMERO_DOIS");
  // Obtém o final do tempo
  auto end = std::chrono::system_clock::now();
  // Diferença do tempo para saber quanto tempo foi gasto
  auto diff = 
    std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
  // Imprime o temp gasto
  std::cout << "Tempo gasto para a requisição: " << 
    diff << " Segundos" << '\n';
  // Imprime a saída
  std::cout <<
    "Primeira API: "<< first_api <<
    "\nSegunda  API: " << second_api << '\n';
  return 0;
}A saída desse exemplo será 4 segundos, pois será somado o tempo da 1º API(2 segundos) mais o tempo da 2º API(2 segundos).
Tempo gasto para a requisição: 4 Segundos
Primeira API: FIRST_NUMERO_UM
Segunda  API: SECOND_NUMERO_DOISOu seja, um foi executado após o outro.
Agora vamos utilizar o mesmo código, mas vamos incluir somente TRÊS linhas para usar o std::async:
#include <future>// Solicita os dados da primeira API, vamos alterar a linha para essa linha:std::future<std::string> result_api_one = std::async(std::launch::async, get_first_data_api, "NUMERO_UM");std::string first_api = result_api_one.get();Perceba que estamos agora utilizando std::future para obter os dados via a função get().
std::async
vim exemplo-com-async.cpp
O código final com uso de std::async ficaria assim:
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <future>
std::string get_first_data_api(std::string ret_data){
  // sleep de 2 segundos
  std::this_thread::sleep_for( std::chrono::seconds(2));
  return "FIRST_" + ret_data;
}
std::string get_second_data_api(std::string ret_data){
  // sleep de 2 segundos
  std::this_thread::sleep_for( std::chrono::seconds(2));
  return "SECOND_" + ret_data;
}
int main(){
  // Obtém o início do tempo para a contagem
  std::chrono::system_clock::time_point start = 
    std::chrono::system_clock::now();
  // Solicita os dados da primeira API
  std::future<std::string> result_api_one = std::async(std::launch::async, get_first_data_api, "NUMERO_UM");
  // Solicita os dados da segunda API
  std::string second_api = get_second_data_api("NUMERO_DOIS");
  // Bloqueará até que os dados estejam disponíveis no objeto future<std::string>.
  std::string first_api = result_api_one.get();
  // Obtém o final do tempo
  auto end = std::chrono::system_clock::now();
  auto diff = 
    std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
  std::cout << "Tempo gasto para a requisição: " << 
    diff << " Segundos" << '\n';
  // Imprime a saída
  std::cout <<
    "Primeira API: "<< first_api <<
    "\nSegunda  API: " << second_api << '\n';
  return 0;
}Para compilar precisamos utilizar a flag: -pthread, exemplo:
g++ -pthread exemplo-com-async.cpp
Agora note que a saída foram gastos somente 2 segundos, ou seja, a primeira API foi executada de forma paralela à segunda API, a saída será:
Tempo gasto para a requisição: 2 Segundos
Primeira API: FIRST_NUMERO_UM
Segunda  API: SECOND_NUMERO_DOISAgora ficou mais fácil de entender, né?
Por hoje é só, são pequenas doses diárias que farão sempre nos manter antenado com o C++ !
Então se inscreva nos nossos Cursos de C++ Moderno . Você aprender criar:
Acesse o endereço: