Comment définir un délai d’attente pour une fonction en C?

J’ai l’obligation de donner xx ms pour exécuter une fonction. Après xx ms, je dois abandonner cette fonction. S’il vous plaît aidez-moi comment le mettre en œuvre en C.

Je pense que la meilleure façon de faire cela implique des pthreads. Démarrez le calcul qui doit éventuellement être annulé dans son propre thread et utilisez dans le thread principal 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; } 

vous pouvez comstackr et exécuter ceci sur Linux avec:

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

Si vous n’utilisez pas pthreads, vous pouvez également utiliser une fonction de délai d’expiration similaire à l’aide d’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 en utilisant une commande comme celle-ci

gcc -o exemple exemple.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 

Je ne connais pas cette architecture, je ne peux donc vous donner qu’un indice général. J’essaierais quelque chose de similaire au vieux mécanisme TRAP de Symbian.

  1. Dans la routine principale:

    • démarrer une timer.
    • mettre de côté un pointeur de stack
    • rangez un compteur de programme.
    • appelez votre fonction.
  2. Dans la routine de traitement des exceptions de timer (interruption). Ceci est un peu délicat car vous devez savoir où, dans une architecture donnée, les pointeurs et les compteurs de programme sont conservés (feuille de données du processeur) lorsque la gestion des exceptions débute. Le compteur de programme a probablement été placé dans la stack de routine principale. Donc, vos étapes sont les suivantes:

    • remplacez la valeur du pointeur de stack (pour la routine principale) par votre valeur copiée.
    • remplacez la valeur du compteur du programme par votre valeur copiée + offset (car vous souhaitez revenir à l’exécution après votre appel de fonction – il est préférable de vérifier le code d’assemblage pour savoir quelle est sa taille).
    • retour de routine de traitement d’exception (interruption).

@Bobby Powers répond, c’est du travail, mais il faut un peu de changement comme ci-dessous

 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.