2010-10-22 17 views
2

J'utilise le compilateur GCC et C++ et je veux faire une minuterie qui déclenche une interruption lorsque le compte à rebours est 0.Comment mettre en œuvre une minuterie avec interruption en C++?

Des idées? Merci d'avance.

EDIT

Merci à Adam, je sais comment le faire.

Maintenant. Qu'en est-il des multiples temporisateurs fonctionnant en parallèle?

En fait, ces minuteurs sont pour quelque chose de très basique. Dans NCURSES, j'ai une liste de choses. Lorsque j'appuie sur une touche, l'une des choses changera de couleur pendant 5 secondes. Si j'appuie sur une autre touche, une autre chose dans la liste fera la même chose. C'est comme souligner les chaînes en fonction de l'entrée de l'utilisateur. Y a-t-il une façon plus simple de faire cela?

+3

Ce n'est pas assez d'informations sur l'application. S'agit-il d'une application de ligne de commande, d'un service de réseau graphique en arrière-plan ou quoi? A-t-il déjà une boucle d'événement principal? Utilise-t-il un cadre pour cela? –

+0

Le programme utilise l'interface ncurses. Et oui, il a une boucle d'événement principal. – Tomas

Répondre

2

Une façon de le faire est d'utiliser l'appel système alarm(2) d'envoyer un SIGALRM à votre processus lorsque le temps imparti:

void sigalrm_handler(int sig) 
{ 
    // This gets called when the timer runs out. Try not to do too much here; 
    // the recommended practice is to set a flag (of type sig_atomic_t), and have 
    // code elsewhere check that flag (e.g. in the main loop of your program) 
} 

... 

signal(SIGALRM, &sigalrm_handler); // set a signal handler 
alarm(10); // set an alarm for 10 seconds from now 

Prenez note des mises en garde dans la page de manuel de alarm:

alarme() et setitimer() partagent la même minuterie; les appels à l'un interféreront avec l'utilisation de l'autre.

sleep() peut être mis en œuvre à l'aide SIGALRM; mélange d'appels à alarm() et sleep() est une mauvaise idée.

Les retards de planification peuvent, comme toujours, entraîner un retard de l'exécution du processus d'une durée arbitraire.

+0

Super, c'est exactement ce dont j'avais besoin. Merci! – Tomas

3

Un moyen facile et portable d'implémenter une minuterie d'interruption utilise Boost.ASIO. Plus précisément, le boost::asio::deadline_timer class vous permet de spécifier une durée et un gestionnaire d'interruptions qui seront exécutés de manière asynchrone lorsque le délai est écoulé. Voir here pour un tutoriel et une démonstration rapide.

-1

Voici un moyen de résoudre ce problème à faire bien à la fois du temps et de l'espace (« complexité ») et ne jamais utiliser plus d'un « timer événement » des services du système d'exploitation.

(1) Terminologie

Commençons d'être un peu clair sur terminologie et essayez d'être plus clair en donnant quelques exemples hypothétiques:

Ainsi, dans notre travail, que le temps passe, nous découvrir (recevoir) des «événements»; nous recevons ces événements à peut-être quelques milliers ou plus par seconde; chaque événement a un 'temps', qui est, heure de l'horloge sur le mur, généralement à l'avenir, lorsque l'événement doit provoquer une 'action' (déclencher, déclencher, générer un interruption, message, condition, etc.). Pour l'événement qui a le plus tôt, nous voulons provoquer l'action au moment de cet événement ou dès que nous pouvons après cela temps.

Ainsi, par analogie, notre problème est comme TO Liste des tâches:


événement

= conférence vidéo avec CA

temps = 9h15

action = lancer la vidéo logiciel


événement = prendre la douche

temps = 7h00

l'action

= SO suite


événement

= réveil

temps = 6h45

l'action

= jouer Anvil Choeur


(2) Première catégorie Solu tion

Choisissez un entier positif n, disons, 1024.

Aller à la 'sorte de tas' algorithme classique et d'allouer et de définir un tas dans le tableau x (1), x (2), .. ., x (n). Chaque composant de ce tableau peut être utilisé pour stocker les données pour un événement.

Soit l'entier m le nombre d'événements dans le tas maintenant. Commencez par m = 0. Nous aurons toujours < = n. Dans le cas après allouer notre tableau de n composants nous découvrons que nous avons plus d'événements à stocker que n, nous modifions cette solution de première classe à la solution de deuxième grade ci-dessous.

En un tas, les composants doivent avoir une «commande» basée sur une «clé». Dans notre tas, les touches sont l'horloge sur le mur fois des événements.

Examiner, pour nombre entier positif i = 1, 2, ..., m, pour le composant de matrice x (i), laisse k (x (i)) la valeur de la clé de ce composant. Ensuite, le (croissant) ' tas état' est, pour i = 2, 3, ..., m, et avoir permis i/2 soit la partie entière de ce quotient ,

k (x (i/2)) < k (x (i))

donc un tas est pas vraiment « trié », mais est une façon intelligente et « implicite » pour stocker un arbre ramifié 2 voies .

Il y a deux 'opérations de tas', une plus rapide, une une et une plus lente, utilisée pour établir la condition de tas. L'opération plus rapide prend un tas de m < n composants et un nouvel événement , met l'événement dans le composant x (m + 1), considère la condition de tas pour i = m + 1 et les échanges si nécessaire, etc., et définit finalement m = m + 1. L'opération plus lente a un tas de m composants, pour certains i = 1, 2, ..., m - 1, supprime l'événement dans le composant x (i), et travaille pour mettre un événement en x (i) et établir un tas de m - 1 composants. Pour les détails, voir un texte sur les algorithmes et les structures de données, par exemple, Knuth 'The Art of Computer Programmation: Tri et Recherche' ou juste de travailler les détails comme un exercice.

Nous voulons que notre tas d'être en « ascendant » pour le temps, qui est, de sorte que x (1) a l'événement avec le plus tôt (comme commun et pratique, nous supposons que notre ordinateur horloge a assez de «résolution» que chaque événement peut être unique, comme ci-dessous, ayant chaque fois unique enlève des événements avant que leurs actions ont été prises au cas où nous voulons faire cela).

Supposons que nous recevons un événement:

Si le temps de cet événement est antérieure à l'heure actuelle, nous juste cause l'action de cet événement. Oui, pour certaines applications , nous pourrions vouloir modifier cette étape si nous anticipons certains cas d'événements arrivant plus vite que nous pouvons prendre les actions ; Je discute de ce point ci-dessous.

Sinon nous avons mis l'événement dans le composant m + 1 du tableau et effectuer (plus vite) un des deux opérations de tas classiques pour établir à nouveau la condition de tas.

Si maintenant m = 1, alors nous demandons au système d'exploitation des services pour une interruption au moment de l'événement dans le composant de tableau x (1).

Si m> 1 et établir le tas état a changé à nouveau le temps de l'événement dans le composant de tableau x (1), nous annulons les services du système d'exploitation interruption et demander une interruption au moment pour l'événement maintenant dans x (1).

Lorsque nous obtenons une interruption, nous prenons l'action de l'événement dans le composant de tableau x (1) et réglez m = m - 1. Maintenant tableau x composant (1) n'a pas l'événement et est « vide '. Donc, nous devons corriger le composant 'vide' x (1) et, en particulier, pour établir à nouveau la condition de tas. Pour cette fin, si m> 0, alors nous utilisons (le plus lent) l'une des deux opérations de tas et, ensuite, demander aux services du système d'exploitation pour une interruption au moment de l'événement maintenant dans le composant tableau x (1).

Nous pouvons soutenir l'annulation d'un événement: Compte tenu le temps (encore une fois, chaque fois est unique) de l'événement, en utilisant le fait que le tas stocke vraiment un arbre binaire, trouver l'événement dans le tas, retirez il, et établir à nouveau la condition de tas.

(3) Application connexes

Supposons que nous recevons 2 milliards de numéros un à la fois et à la fin voulez avoir le plus petit 20. Ou, si nous voulons le 20 plus grand, alors nous utilisons un tas ascendant.

(4) Deuxième solution grade

Si nous découvrons que n est trop petit, alors que nous considérons le tas ci-dessus comme une « feuille ». Ensuite, pour un entier positif k, nous construisons un arbre équilibré k-way où les leafs sont n tas de composants comme ci-dessus et les noeuds sont des tas k-composant qui pointent vers les noeuds ou feuilles dans l'arbre plus loin de la racine de l'arbre.

Lorsque nous avons besoin de plusieurs nœuds ou feuilles dans l'arborescence , nous allouons le stockage. Comme d'habitude, nous peut sélectionner un entier positif p et en fait jamais nœud libre heaps à moins de que p, et sélectionnez entiers positifs q et en fait jamais stockage de feuille libre à moins de que q. De cette façon, nous pouvons «lisser» le nombre d'allocations de stockage ou demandes gratuites à notre gestionnaire d'allocation de stockage dynamique .

Oui, ici, nous pourrions faire un peu d'optimisation départ de mathématiques avec des coûts d'allocation de stockage et de libérer et quelques hypothèses sur le « processus d'arrivée stochastique » des événements. En raison du fameux théorème de renouvellement dans les processus stochastiques , on peut supposer que le processus d'arrivée est juste un processus de Poisson non stationnaire avec un taux d'arrivée variant lentement à .

(5) Détail de devenir trop occupé

Il se peut que parfois les événements arrivent plus vite que nous pouvons prendre leurs actions. Ainsi, à 10h02 nous pouvons avoir 8 022 événements qui sont arrivés mais pour lesquels nous avons pris aucune action et avec tous les temps de les événements plus tôt que l'heure 10:02. Maintenant quoi? Eh bien nous pourrions encore aimer exécuter les événements dans l'ordre croissant sur fois. Donc, nous pouvons aller de l'avant et mettre les événements dans le tas et/ou l'arborescence équilibrée jusqu'à ce qu'ils soient 'rattrapés' et puis prendre les actions dans l'ordre croissant sur temps.

(6) Problème: Comment modifier pour de nombreux noyaux ?