web-dev-qa-db-fra.com

c ++, usleep () est obsolète, des solutions de contournement pour Windows / MingW?

J'ai déjà découvert avec une autre question que Windows/MingW ne fournit pas les alternatives nanosleep () et setitimer () à usleep () obsolète. Mais mon objectif est de corriger tous les avertissements que cppcheck me donne, y compris les avertissements de style usleep ().

Alors, existe-t-il une solution de contournement pour éviter en quelque sorte usleep () sous Windows sans en utilisant cygwin ou en installant des charges de nouvelles dépendances/bibliothèques? Merci.

22
blubberbernd

Nouvelle réponse à une ancienne question:

Justification de la nouvelle réponse: les outils/systèmes d'exploitation ont été mis à jour de sorte qu'il y a maintenant un meilleur choix que lors de la question initiale.

Le C++ 11 <chrono> et <thread> Les en-têtes std font partie du jeu d'outils VS depuis plusieurs années. L'utilisation de ces en-têtes est mieux codée en C++ 11 comme:

std::this_thread::sleep_for(std::chrono::microseconds(123));

J'utilise les microsecondes uniquement comme exemple de durée. Vous pouvez utiliser la durée qui vous convient:

std::this_thread::sleep_for(std::chrono::minutes(2));

Avec C++ 14 et certaines directives d'utilisation, cela peut être écrit un peu plus compact:

using namespace std::literals;
std::this_thread::sleep_for(2min);

ou:

std::this_thread::sleep_for(123us);

Cela fonctionne certainement sur VS-2013 (modulo les chrono-littéraux). Je ne suis pas sûr des versions antérieures de VS.

12
Howard Hinnant

Le régime en millisecondes de la fonction Sleep() est bien décrit et bien compris. Cela ne fait rien d'imprévisible. Parfois, la fonction est accusée d'être imprévisible, c'est-à-dire de revenir avant l'expiration du délai. Je dois dire que c'est faux. Une enquête approfondie confirmera que son comportement est absolument prévisible. Le seul problème est qu'il y a beaucoup à lire à ce sujet et que la plupart est kiddish. On dit aussi souvent que Windows n'est pas un système d'exploitation en temps réel. Mais de tels commentaires ne contribuent en rien, d'ailleurs ces commentaires servent à masquer le manque de connaissances. Cela me met en colère, car même Microsoft ne le remarque pas et fournit une meilleure documentation.

Cependant, sans exagérer cette petite réponse: La fonction sleep () est précise, lorsqu'elle est utilisée correctement et en connaissant ses caractéristiques. Une attention particulière doit être accordée au sommeil (0). Il s'agit d'un outil très puissant, particulièrement lorsqu'il est utilisé avec la classe de priorité de processus, la priorité de thread, les paramètres de minuterie multimédia et le masque d'affinité du processeur.

Donc, généralement, un véritable sommeil peut être effectué facilement et en toute sécurité jusqu'à la période d'interruption du système. En ce qui concerne le sommeil plus court que la période d'interruption, la rotation est nécessaire. Une source de temps de résolution plus élevée doit être utilisée de manière à tourner pour des périodes plus courtes. La source la plus courante pour cela est le compteur de performances. QueryPerformanceCounter(*arg) fournit un argument incrémentiel *. QueryPerformanceFrequency(*arg) fournit la fréquence à laquelle le compteur de performances augmente. Ceci est généralement dans le régime MHz et varie en fonction du matériel sous-jacent. Une fréquence de l'ordre de MHz fournit une résolution en microsecondes. De cette façon, quelque chose de haute résolution peut être utilisé pour attendre l'expiration du laps de temps souhaité. Cependant, la précision de ceci doit être examinée attentivement: le système d'exploitation renvoie la fréquence du compteur de performances sous forme de constante. C'est faux! Puisque la fréquence est générée par un appareil physique, il y a toujours un décalage et ce n'est pas non plus une constante. Il a une dérive thermique. Les systèmes plus modernes ont moins de dérive. Mais si la dérive thermique n'est que de 1 ppm, l'erreur sera de 1 us/s. Le décalage peut facilement être de plusieurs 100. Un décalage de 100 à 1 MHz correspond à 100us/s.

Si un thread doit attendre un moment à haute résolution, il doit établir un thread de service. Les deux threads doivent partager un événement nommé. Le thread de service doit rester en veille jusqu'à 1 période d'interruption avant le délai de sommeil souhaité, puis tourner sur le compteur de performances pendant la microseconde restante. Lorsque le thread de service atteint l'heure finale, il définit l'événement nommé et se termine. Le thread appelant se réveillera, car il attendait l'événement nommé au moyen d'une fonction d'attente.

Sommaire:

  • Le sommeil est bien compris mais mal documenté.
  • Un thread de service peut imiter les mises en veille à haute résolution.
  • Un tel fil de service peut être établi en tant que service à l'échelle du système.
  • La précision du compteur de performances doit être examinée attentivement. Un étalonnage est nécessaire.

Des informations plus détaillées peuvent être trouvées sur le Projet d'horodatage Windows

8
Arno

J'ai trouvé ce blog à ce sujet . Il utilise QueryPerformanceCounter. La fonction a posté:

#include <windows.h>

void uSleep(int waitTime) {
    __int64 time1 = 0, time2 = 0, freq = 0;

    QueryPerformanceCounter((LARGE_INTEGER *) &time1);
    QueryPerformanceFrequency((LARGE_INTEGER *)&freq);

    do {
        QueryPerformanceCounter((LARGE_INTEGER *) &time2);
    } while((time2-time1) < waitTime);
}

J'espère que cela aide un peu.

5
orlp

Cela dépend de la granularité dont vous avez besoin. Si vous parlez en millisecondes, la fonction Win32 Sleep fera le travail - voir http://msdn.Microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx =. Si vous parlez de microsecondes, il n'y a pas de moyen facile de le faire, et vous auriez la chance d'obtenir ce type de résolution de minuterie sur Windows (qui n'est pas un RTOS), ou sur Linux, venez à cela.

5
Neil Butterworth