Luego de de esta prolongada recopilación de información pudimos solucionar esta cuestión que presentan muchos los usuarios. Te compartimos la respuesta y nuestro deseo es resultarte de mucha apoyo.
Solución:
Puede crear un subproceso separado para ejecutar la llamada en sí y esperar una variable de condición en su subproceso principal que será señalado por el subproceso que realiza la llamada a f
una vez que regresa. El truco es esperar en la variable de condición con su tiempo de espera de 1s, de modo que si la llamada toma más tiempo que el tiempo de espera, aún se despertará, lo sabrá y podrá lanzar la excepción, todo en el hilo principal. Aquí está el código (demostración en vivo aquí):
#include
#include
#include
#include
#include
using namespace std::chrono_literals;
int f()
std::this_thread::sleep_for(10s); //change value here to less than 1 second to see Success
return 1;
int f_wrapper()
std::mutex m;
std::condition_variable cv;
int retValue;
std::thread t([&cv, &retValue]()
retValue = f();
cv.notify_one();
);
t.detach();
std::unique_lock l(m);
if(cv.wait_for(l, 1s) == std::cv_status::timeout)
throw std::runtime_error("Timeout");
return retValue;
int main()
bool timedout = false;
try
f_wrapper();
catch(std::runtime_error& e)
std::cout << e.what() << std::endl;
timedout = true;
if(!timedout)
std::cout << "Success" << std::endl;
return 0;
También puede usar std::packaged_task para ejecutar su función f() en otro hilo. Esta solución es más o menos similar a esta, solo que usa clases estándar para terminar.
std::packaged_task task(f);
auto future = task.get_future();
std::thread thr(std::move(task));
if (future.wait_for(1s) != std::future_status::timeout)
thr.join();
future.get(); // this will propagate exception from f() if any
else
thr.detach(); // we leave the thread still running
throw std::runtime_error("Timeout");
Probablemente incluso pueda intentar envolverlo en una plantilla de función, para permitir llamar a funciones arbitrarias con tiempo de espera. Algo del estilo de:
template
std::result_of_t run_with_timeout(TF&& f, TDuration timeout, TArgs&&... args)
using R = std::result_of_t;
std::packaged_task task(f);
auto future = task.get_future();
std::thread thr(std::move(task), std::forward(args)...);
if (future.wait_for(timeout) != std::future_status::timeout)
thr.join();
return future.get(); // this will propagate exception from f() if any
else
thr.detach(); // we leave the thread still running
throw std::runtime_error("Timeout");
Y luego usa:
void f1() ...
call_with_timeout(f1, 5s);
void f2(int) ...
call_with_timeout(f2, 5s, 42);
int f3() ...
int result = call_with_timeout(f3, 5s);
Este es un ejemplo en línea: http://cpp.sh/7jthw
Puede crear un nuevo subproceso y esperar asincrónicamente a que pasen 1 y luego lanzar una excepción. Sin embargo, las excepciones solo se pueden capturar en el mismo subproceso en el que se lanzan, por lo que no se pueden capturar en el mismo subproceso en el que llamó f()
como en su código de ejemplo, pero ese no es un requisito establecido, por lo que puede estar bien para usted.
Sólo si f
se garantiza que regresará en menos de 1 segundo, ¿puede hacerlo de forma sincrónica?
- almacenar la hora actual
- llamar
f()
- esperar la hora actual - tiempo almacenado + 1s
Pero puede ser bastante difícil demostrar que f
de hecho regresa a tiempo.