Quelle est la meilleure façon de sortir d'une boucle après un temps écoulé de 30ms en C ++

StackOverflow https://stackoverflow.com/questions/946167

  •  09-09-2019
  •  | 
  •  

Question

Quelle est la meilleure façon de sortir d'une boucle aussi près que possible 30ms en C ++. coup de pouce de vote: microsec_clock? QTime de relève? Quelque chose d'autre?

Quelque chose comme:

A = now;
for (blah; blah; blah) {
    Blah();
    if (now - A > 30000)
         break;
}

Il devrait fonctionner sous Linux, OS X et Windows.

Les calculs de la boucle sont pour la mise à jour d'une simulation. Tous les 30ms, je souhaite mettre à jour la fenêtre.

Était-ce utile?

La solution

L'exemple d'extrait de code dans ce lien à peu près fait ce que vous voulez:

http://www.cplusplus.com/reference/clibrary/ctime/ horloge /

Adapté de leur exemple:

void runwait ( int seconds )
{
   clock_t endwait;
   endwait = clock () + seconds * CLOCKS_PER_SEC ;
   while (clock() < endwait)
   {
      /* Do stuff while waiting */
   }
}

Autres conseils

  

Les calculs effectués dans la boucle sont pour   la mise à jour d'une simulation. Tous les 30ms, je   comme de mettre à jour la fenêtre.

Avez-vous envisagé d'utiliser des fils? Ce que vous décrivez semble l'exemple parfait de la raison pour laquelle vous devez utiliser des fils au lieu de minuteries.

Le thread principal processus continue à prendre soin de l'interface utilisateur, et un QTimer mis à 30ms pour le mettre à jour. Il verrouille QMutex pour avoir accès aux données, effectue la mise à jour, et libère le mutex.

Le deuxième fil (voir QThread ) effectue la simulation. Pour chaque cycle, il verrouille le QMutex, effectue les calculs et libère le mutex lorsque les données sont dans un état stable (approprié pour la mise à jour de l'interface utilisateur).

Avec la tendance croissante sur les processeurs multi-core, vous devriez penser de plus en plus sur l'utilisation de threads que sur l'utilisation de minuteries. Vos applications bénéficie automatiquement de la puissance accrue (plusieurs noyaux) de nouveaux processeurs.

Bien que cela ne répond pas à la question, il pourrait donner un autre regard sur la solution. Qu'en est-il de placer le code de simulation et de l'interface utilisateur dans différents threads? Si vous utilisez Qt, mise à jour périodique peut être réalisée à l'aide d'une minuterie ou même QThread :: msleep ( ) . Vous pouvez adapter le fileté exemple Mandelbrot pour répondre à vos besoins.

Si vous devez faire le travail jusqu'à ce qu'un certain temps se soit écoulé, puis réponse de docflabby est sur place. Toutefois, si vous avez juste besoin d'attendre, sans rien faire, jusqu'à ce qu'un temps soit écoulé, vous devez utiliser usleep()

Réponse courte est: vous ne pouvez pas en général, mais vous pouvez si vous exécutez sur le droit OS ou sur le bon matériel

.

Vous pouvez Rapprochez à 30ms sur tous les systèmes d'exploitation à l'aide d'un appel de montage sur les systèmes Intel et quelque chose d'autre sur d'autres architectures. Je vais déterrer la référence et modifier la réponse à inclure le code quand je trouve.

Le problème est l'algorithme de découpage en tranches de temps et la proximité de la fin de votre tranche de temps vous êtes sur un système d'exploitation multi-tâches.

Sur certains systèmes d'exploitation en temps réel, il y a un appel système dans une bibliothèque de système que vous pouvez faire, mais je ne suis pas sûr de ce que cet appel serait.

edit: LOL! Quelqu'un déjà posté un extrait sur le SO similaire: fonction de minuterie pour donner le temps en nanosecondes en C ++

VonC a obtenu le commentaire avec le code assembleur de la minuterie CPU en elle.

Selon votre question, tous les 30ms que vous souhaitez mettre à jour la fenêtre. J'ai écrit une application similaire une fois que le matériel sondé toutes les 500ms pour des choses semblables. Bien que cela ne répond pas directement à votre question, je les followups suivants:

  • Etes-vous sûr Blah (), pour mettre à jour la fenêtre, peut exécuter en moins de 30 ms dans tous les cas?
  • Semble plus comme la course Blah () serait mieux fait par un rappel de la minuterie.
  • Il est très difficile de trouver un objet timer bibliothèque qui va pousser sur un intervalle de 30 ms pour faire des mises à jour dans un cadre graphique. Sous Windows XP, je trouve que la minuterie API Win32 standard qui pousse les messages de la fenêtre à l'expiration d'intervalle de temporisation, même sur un 2GHz P4, ne pouvait pas faire des mises à jour plus rapidement qu'un intervalle 300ms, quelle que soit la faible je régler l'intervalle de temps pour le minuteur. Alors qu'il y avait des minuteries de haute performance disponibles dans l'API Win32, ils ont beaucoup de restrictions, à savoir que vous ne pouvez pas faire IPC (comme les widgets de l'interface utilisateur de mise à jour) dans une boucle comme celui que vous avez cité ci-dessus.
  • Au fond, le résultat est que vous devez planifier très attentivement la façon dont vous voulez avoir mises à jour. Vous devrez peut-être utiliser les threads, et regardez comment vous souhaitez mettre à jour la fenêtre.

Juste quelques choses à penser. Ils me pris par surprise quand je travaillais sur mon projet. Si vous avez pensé à ces choses à travers déjà, s'il vous plaît ne pas tenir compte ma réponse. 0)

Vous pourriez envisager juste mettre à jour la fenêtre toutes les étapes de simulation N plutôt que toutes les millisecondes K. Si cela est (par exemple) une application commerciale sérieuse, alors vous allez probablement vouloir aller la route multi-thread suggéré ailleurs, mais si (par exemple), il est pour un usage personnel ou public limité et ce que vous êtes vraiment intéressé par est les détails de quoi que ce soit vous êtes simulent, puis tous-N-étapes est simple, portable et peut bien être assez bon pour être obtenir avec.

Voir QueryPerformanceCounter et QueryPerformanceFrequency

Si vous utilisez Qt, voici un moyen simple de faire ceci:

QTimer* t = new QTimer( parent ) ;
t->setInterval( 30 ) ; // in msec
t->setSingleShot( false ) ;
connect( t, SIGNAL( timeout() ), viewPort, SLOT( redraw() ) ) ;

Vous devez spécifier viewPort et redraw(). Ensuite, démarrez la minuterie avec t->start().

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top