HOWTO · C++
Ajouter un délai temporisé en C++
Ce didacticiel vous donnera un bref guide sur l'ajout d'un délai temporisé dans votre programme C++.
Sur cette page
Un programme C++ peut suspendre son thread courant au moyen d’une API propre à la plateforme ou des fonctions d’attente de threads de la bibliothèque standard. Choisissez selon la portabilité souhaitée et selon que l’attente porte sur une durée ou sur une heure précise : sur les systèmes POSIX, sleep() prend des secondes entières et usleep() des microsecondes ; depuis C++11, sleep_for() et sleep_until() acceptent respectivement des durées et des points temporels. Ces appels suspendent le thread appelant sans garantir sa reprise à un instant exact.
Choisir une API de temporisation en C++
Pour une attente relative portable en C++11 dans une application classique, utilisez sleep_for(). Choisissez sleep_until() lorsqu’un traitement doit attendre une échéance définie sur une horloge. Les fonctions POSIX sleep() et usleep() conviennent au code déjà lié à POSIX, mais ne font pas partie des fonctionnalités C++ portables. Windows fournit sa propre API Sleep(), dont l’argument est exprimé en millisecondes.
Une temporisation bloque le thread qui l’appelle. Si une interface utilisateur, un serveur ou un groupe de threads de travail doit rester réactif, utilisez un thread dédié ou le minuteur asynchrone du framework au lieu de bloquer le thread principal ou celui de la boucle d’événements.
Utiliser sleep() pour des délais propres à la plateforme, en secondes entières
C++ ne définit pas de fonction portable sleep(). Sur les systèmes POSIX, déclarez-la avec <unistd.h> et appelez sleep(secondes). Si un signal interrompt l’attente, la fonction renvoie le nombre de secondes entières restant à attendre ; elle renvoie zéro lorsque l’intervalle demandé est écoulé. Sous Windows, incluez <Windows.h> et appelez Sleep(millisecondes) : l’unité étant la milliseconde, une seconde d’attente correspond à Sleep(1000). Les appels POSIX et Windows ont des noms, des en-têtes et des unités différents. L’en-tête Windows est également présenté dans le guide Windows.h, disponible ici en anglais ; l’inventaire ne fournit pas de destination française.
Par exemple, sous POSIX, après avoir inclus <unistd.h>, l’appel est sleep(2);. Sous Windows, après avoir inclus <Windows.h>, utilisez Sleep(2000);. Choisissez la branche correspondant à la plateforme cible : une déclaration POSIX ne rend pas sleep() disponible sous Windows.
Utiliser usleep() pour des délais POSIX en microsecondes
Sur les systèmes POSIX, usleep() est déclarée dans <unistd.h> et accepte une durée en microsecondes. Par exemple, usleep(250000); demande une pause d’un quart de seconde. Il s’agit d’une interface POSIX, et non d’une fonctionnalité C++ portable ; certaines plateformes ou configurations de fonctionnalités peuvent ne pas la fournir. Pour du code C++ multiplateforme, utilisez donc sleep_for(). La fonction renvoie 0 lorsque l’attente se termine et -1 si elle est interrompue ou échoue pour une autre raison. Vérifiez sa valeur de retour si le programme doit réagir à une interruption. La durée réellement écoulée peut dépasser l’intervalle demandé, car le système d’exploitation planifie les threads selon son propre fonctionnement.
Utiliser sleep_for() pour une attente relative
Incluez <thread> et <chrono> pour attendre une durée relative. sleep_for() suspend le thread courant pendant au moins la durée demandée, sous réserve de l’ordonnancement et de la concurrence pour les ressources. Ce programme C++11 complet marque une pause de 200 millisecondes, puis affiche un message de confirmation. Le texte affiché reste en anglais dans l’exemple, dont le bloc est conservé à l’identique. Exécutez cet exemple :
#include <chrono>
#include <iostream>
#include <thread>
int main() {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "Wait complete\n";
}
Wait complete
Utilisez un type de durée qui rend l’unité voulue explicite, par exemple std::chrono::seconds(2) ou std::chrono::milliseconds(250). L’attente ne concerne que le thread appelant ; les délais d’ordonnancement peuvent prolonger le temps écoulé au-delà de la durée transmise à la fonction.
Utiliser sleep_until() pour attendre un point temporel
sleep_until() provient également de <thread>, mais accepte un point temporel d’une horloge plutôt qu’une durée. Ajoutez une durée à la valeur now() d’une horloge pour former une échéance future. Par exemple : std::this_thread::sleep_until(std::chrono::steady_clock::now() + std::chrono::seconds(3));. L’attente se poursuit jusqu’à ce point sur steady_clock, conçue pour mesurer des intervalles et qui, contrairement à l’heure civile, n’est pas ajustée. Une échéance déjà passée n’ajoute aucun temps d’attente. La fonction ne renvoie aucune valeur, et l’ordonnanceur peut reprendre le thread après l’échéance.
Pour les échéances mesurées en temps écoulé, préférez steady_clock afin qu’une correction de l’horloge système ne déplace pas la cible. N’utilisez system_clock que si vous visez une heure civile, et tenez compte des changements de cette horloge pendant l’attente. Comme sleep_for(), cette fonction bloque le thread appelant.
Choisir le bon délai et tenir compte de l’ordonnancement
Pour du code C++11 portable, utilisez sleep_for() lorsque le besoin est « attendre pendant cette durée » et sleep_until() lorsqu’il s’agit d’« attendre jusqu’à cette échéance ». Réservez sleep() et usleep() au code qui dépend de POSIX, et utilisez Sleep() dans le code propre à Windows. Gardez les unités à l’esprit : sleep() prend des secondes, usleep() des microsecondes, Sleep() sous Windows des millisecondes, et <chrono> représente les durées à l’aide de types nommés.
Aucune de ces API n’est un minuteur de précision. La durée demandée constitue un seuil d’attente minimal, et non une garantie quant à l’instant exact de reprise ; l’ordonnancement, la concurrence pour les ressources et les interruptions influent sur le moment où l’exécution reprend. Pour de courtes attentes qui ne doivent pas bloquer un thread, utilisez un minuteur asynchrone fourni par la plateforme ou le framework. Cette distinction aide à choisir un délai adapté aux besoins de portabilité du programme et à son modèle temporel.