¿Cómo establecer un tiempo de espera para una función en C?

Tengo el requisito de que debo dar xx ms para ejecutar una función. Después de xx ms tengo que abortar esa función. Por favor ayúdame a implementarlo en C.

Creo que la mejor manera de hacer esto involucra pthreads. Inicie el cálculo que posiblemente deba cancelarse en su propio hilo, y en el hilo principal use pthread_cond_timedwait:

#include  #include  #include  /* for ETIMEDOUT */ #include  #include  pthread_mutex_t calculating = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t done = PTHREAD_COND_INITIALIZER; void *expensive_call(void *data) { int oldtype; /* allow the thread to be killed at any time */ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); /* ... calculations and expensive io here, for example: * infinitely loop */ for (;;) {} /* wake up the caller if we've completed in time */ pthread_cond_signal(&done); return NULL; } /* note: this is not thread safe as it uses a global condition/mutex */ int do_or_timeout(struct timespec *max_wait) { struct timespec abs_time; pthread_t tid; int err; pthread_mutex_lock(&calculating); /* pthread cond_timedwait expects an absolute time to wait until */ clock_gettime(CLOCK_REALTIME, &abs_time); abs_time.tv_sec += max_wait->tv_sec; abs_time.tv_nsec += max_wait->tv_nsec; pthread_create(&tid, NULL, expensive_call, NULL); /* pthread_cond_timedwait can return spuriously: this should * be in a loop for production code */ err = pthread_cond_timedwait(&done, &calculating, &abs_time); if (err == ETIMEDOUT) fprintf(stderr, "%s: calculation timed out\n", __func__); if (!err) pthread_mutex_unlock(&calculating); return err; } int main() { struct timespec max_wait; memset(&max_wait, 0, sizeof(max_wait)); /* wait at most 2 seconds */ max_wait.tv_sec = 2; do_or_timeout(&max_wait); return 0; } 

puedes comstackr y ejecutar esto en linux con:

 $ gcc test.c -pthread -lrt && ./a.out do_or_timeout: calculation timed out 

Si no está utilizando pthreads, también puede hacer una función de tiempo de espera similar utilizando Apache Portable Runtime: http://apr.apache.org/docs/apr/1.4/group__apr__thread__proc.html

 #include  #include  #include  #include "apr.h" #include "apr_thread_proc.h" #include "apr_time.h" void *APR_THREAD_FUNC expensive_call(apr_thread_t *thread, void *data) { (void)thread; bool *done = data; /* ... calculations and expensive io here, for example: * infinitely loop */ for (;;) {} // signal caller that we are done *done = true; return NULL; } bool do_or_timeout(apr_pool_t *pool, apr_thread_start_t func, int max_wait_sec) { apr_thread_t *thread; bool thread_done = false; apr_thread_create(&thread, NULL, func, &thread_done, pool); apr_time_t now = apr_time_now(); for (;;) { if (thread_done) { apr_thread_join(NULL, thread); return true; } if (apr_time_now() >= now + apr_time_make(max_wait_sec, 0)) { return false; } // avoid hogging the CPU in this thread apr_sleep(10000); } } int main(void) { // initialize APR apr_initialize(); apr_pool_t *ap; if (apr_pool_create(&ap, NULL) != APR_SUCCESS) { exit(127); } // try to do the expensive call; wait up to 3 seconds bool completed = do_or_timeout(ap, expensive_call, 3); if (completed) { printf("expensive_call completed\n"); } else { printf("expensive_call timed out\n"); } apr_terminate(); return 0; } 

Comstackr usando un comando como este

gcc -o ejemplo example.c -lapr-1

 ->include time.h ->take two variable for start time & current time of type time_t like time_t start_time,current_time -> take start time time(&start_time); now in while loop continuisly check for time(&current_time) difftime(current_time,start_time) if difftime's return value is 15ms break while loop & close your program 

No conozco esa architecture, así que solo puedo darte una pista general. Probaría algo similar al antiguo mecanismo TRAP de Symbian.

  1. En la rutina principal:

    • iniciar un temporizador.
    • guarda un puntero de stack
    • guardar un contador de progtwig.
    • llama a tu función.
  2. En la rutina de manejo de excepciones de temporizador (interrupción). Esto es un poco complicado porque necesita saber dónde se guardan los punteros de stack de architecture y los contadores de progtwig (hoja de datos del procesador) cuando se inicia el manejo de excepciones. El contador de progtwig fue probablemente colocado en la stack de rutina principal. Así que tus pasos son:

    • reemplace el valor del puntero de stack (para la rutina principal) con su valor copiado.
    • reemplace el valor del contador del progtwig con su valor copiado + compensación (porque desea volver a la ejecución después de su llamada a la función; es mejor verificar el código de ensamblaje para asegurarse de su tamaño).
    • Retorno de la rutina de manejo de excepciones (interrupciones).

La respuesta de @Bobby Powers es trabajo, pero necesita un pequeño cambio como se muestra a continuación

 if (!err) pthread_mutex_unlock(&calculating); -> change to pthread_mutex_unlock(&calculating); as @TD Smith says and need add pthread_cancel(tid) // if isn't add, the expensive_call may never exit if your function couldn't exit by itself, such as for (;;) {} or something block operation.