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 ?
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? –
Le programme utilise l'interface ncurses. Et oui, il a une boucle d'événement principal. – Tomas