Question

Je travaille à travers quelques-uns des exercices dans le langage C ++ de programmation par Bjarne Stroustrup. Je suis confus par le problème 11 à la fin du chapitre 12:

(* 5) La conception et la mise en œuvre d'une bibliothèque pour écrire des simulations événementielles. Astuce: . ... Un objet de la tâche de la classe devrait être en mesure d'enregistrer son état et d'avoir cet état restauré afin qu'il puisse fonctionner comme un coroutine. Les tâches spécifiques peuvent être définis comme des objets de classes dérivées de la tâche. Le programme à exécuter par une tâche peut être définie comme une fonction virtuelle. ... Il devrait y avoir un planificateur mettant en œuvre un concept de temps virtuel. ... Les tâches devront communiquer. Concevoir une file d'attente de classe pour cela. ...

Je ne sais pas exactement ce que cela est demandé. Est-ce une tâche un thread séparé? (Pour autant que je sais qu'il est impossible de créer un nouveau thread sans appels système, et puisque c'est un livre sur C ++ je ne crois pas que ce soit l'intention.) Sans interruptions, comment est-il possible de démarrer et d'arrêter une course une fonction? Je suppose que cela impliquerait une attente active (qui est-à-dire la boucle en permanence et vérifier une condition) bien que je ne vois pas comment cela pourrait être appliqué à une fonction qui pourrait ne pas mettre fin à un certain temps (si elle contient une boucle infinie, par exemple) .

EDIT:. S'il vous plaît voir mon post ci-dessous avec plus d'informations

Était-ce utile?

La solution

  

Astuce:.

est une référence à une ancienne coopérative bibliothèque multi-tâches livré avec les premières versions de cfront (vous pouvez également télécharger à cette page).

Si vous lisez le document intitulé « un ensemble de classes C ++ pour la programmation style co-routine » les choses vont faire beaucoup plus de sens.


Ajout d'un bit:

Je ne suis pas un vieux programmeur assez d'avoir utilisé la bibliothèque de tâches. Cependant, je sais que C ++ a été conçu après Stroustrup a écrit une simulation dans Simula qui avait un grand nombre des mêmes propriétés que la bibliothèque de tâches, donc je l'ai toujours été curieux.

Si je devais mettre en œuvre l'exercice du livre, je ferais probablement comme ça (s'il vous plaît noter, je ne l'ai pas testé ce code ou même essayé de le compiler):

class Scheduler {
    std::list<*ITask> tasks;
  public:
    void run()
    {
        while (1) // or at least until some message is sent to stop running
            for (std::list<*ITask>::iterator itor = tasks.begin()
                      , std::list<*ITask>::iterator end = tasks.end()
                    ; itor != end
                    ; ++itor)
                (*itor)->run(); // yes, two dereferences
    }

    void add_task(ITask* task)
    {
        tasks.push_back(task);
    }
};

struct ITask {
    virtual ~ITask() { }
    virtual void run() = 0;
};

Je sais que les gens seront en désaccord avec certains de mes choix. Par exemple, en utilisant une struct pour l'interface; mais struct ont le comportement qui héritant d'eux est public par défaut (où héritant des classes est privée par défaut), et je ne vois aucune valeur en héritant privée d'une interface, alors pourquoi ne pas l'héritage public par défaut?

L'idée est que les appels à iTask :: run () va bloquer le programmateur jusqu'à ce que la tâche arrive à un point où il peut être interrompu, à quel point la tâche sera de retour de la méthode d'exécution, et attendez que les appels de planificateur courir à nouveau pour continuer. La « coopérative » dans « multi-tâches de coopération », « tâches disent quand ils peuvent être interrompus » ( « coroutine » signifie généralement « coopérative multi-tâches »). Une tâche simple ne peut faire une chose dans sa méthode run (), une tâche plus complexe peut mettre en œuvre une machine d'état, et peut utiliser sa méthode run () pour déterminer quel état l'objet est en cours et faire des appels à d'autres méthodes basées sur cet état. Les tâches doit abandonner le contrôle de temps en temps pour que cela fonctionne, parce que c'est la définition de « multi-tâches coopératif. » Il est aussi la raison pour laquelle tous les systèmes d'exploitation modernes n'utilisent pas multi-tâches coopératif.

Cette mise en œuvre n'a pas (1) suivent la planification équitable (en gardant peut-être un total courant de l'horloge ticks passé dans la méthode de l'exécution de la tâche (), et sauter les tâches qui ont utilisé trop de temps par rapport aux autres jusqu'à ce que les autres tâches « prises up "), (2) permettent des tâches à supprimer, ou même (3) permettent le planificateur d'être arrêté.

En ce qui concerne la communication entre les tâches, vous pouvez envisager de regarder Plan 9 de libtask ou newsqueak Rob Pike d'inspiration (la « mise en œuvre UNIX de newsqueak » téléchargement inclut un document intitulé « la mise en œuvre de newsqueak » qui traite de passage de messages dans une machine virtuelle intéressante).

Mais je crois que c'est le squelette de base Stroustrup avait à l'esprit.

Autres conseils

Voici ma compréhension d'une « simulation événementielle »:

  • Un contrôleur gère une file d'attente d'événements, les événements programmant de se produire à certains moments, puis l'exécution de l'événement en haut sur la file d'attente.
  • Événements OCUR instantanément à l'heure prévue. Par exemple, un événement « move » mettrait à jour la position et l'état d'une entité dans la simulation telle que le vecteur d'état est valide au moment de la simulation en cours. Un événement « sens » devrait assurer que les états de toutes les entités sont à l'heure actuelle, utilisez un certain modèle mathématique pour évaluer dans quelle mesure l'entité actuelle peut détecter les autres entités. (Pensez robots se déplacer sur une carte.)
  • Ainsi le temps passe en discontinu, en sautant d'un événement à. Cela contraste avec une simulation par horloge, où le temps se déplace dans des étapes discrètes et les états de toutes les entités sont mises à jour chaque pas de temps (à la plupart des modèles Simulink).
  • Les événements peuvent alors se produire à leur rythme naturel. Il ne habituellement pas de sens de recalculer toutes les données au taux meilleur dans la simulation.

La plupart des simulations événementielles-production fonctionnent dans un seul fil. Ils peuvent être complexes par leur nature même, afin d'essayer de synchroniser une simulation multi-thread tend à ajouter des couches de complexité exponentielle. Cela dit, il y a une norme pour les simulations militaires multi-processus appelé distributive de simulation interactive (DIS) qui utilise des messages TCP prédéfinis pour transmettre des données entre les processus.

EDIT: Il est important de définir une différence entre la modélisation et la simulation. Un modèle est une représentation mathématique d'un système ou d'un procédé. Une simulation est construit à partir d'un ou plusieurs modèles qui sont exécutés sur une période de temps. Encore une fois, un événement basée sur la simulation du houblon d'un événement à, alors qu'un temps de conduite produit de simulation à un pas de temps constant.

me semble l'exercice vous demande de mettre en œuvre un programmateur multi-tâches coopératif. Le planificateur fonctionne dans le temps virtuel (temps vous tiques définir / mettre en œuvre à tous les niveaux que vous voulez), choisit une tâche à exécuter en fonction de la file d'attente (notez que la description dit que vous auriez besoin de mettre en œuvre un), et lorsque la tâche en cours est fait, le planificateur choisit la suivante et commence à fonctionner.

La structure générale d'une simulation d'événements discrets est basée sur une file d'attente prioritaire calée sur une valeur de temps. À un niveau général, il va comme:

    While (not end condition):
        Pop next event (one with the lowest time) from the priority queue
        Process that event, which may generate more events
        If a new event is generated:
            Place this on the priority queue keyed at its generated time

Co-routines changent la vue du modèle d'être à l'être centrée sur l'entité centrée sur l'événement. Les entités peuvent passer par un certain cycle de vie (par exemple accepter l'emploi, saisir des ressources X, travail de processus, ressource version X, le lieu travail en file d'attente pour l'étape suivante). Ceci est un peu plus facile à programmer que les ressources d'appui sont traitées avec des primitives de synchronisation de type sémaphores. Les emplois et les primitives de synchronisation génèrent les événements et les file d'attente dans les coulisses.

Cela donne un modèle conceptuel semblable aux processus dans un système d'exploitation et un programmateur de veille du processus en place lorsque son entrée ou une ressource partagée, il a demandé est disponible. Le modèle de co-routine fait la simulation beaucoup plus facile à comprendre, ce qui est utile pour la simulation des systèmes complexes.

(Je ne suis pas C ++ dev)

Probablement ce que cela signifie est que vous devez créer une classe de tâches (comme dans l'événement) qui se compose principalement d'un pointeur de fonction de rappel et une heure programmée, et peut être stocké dans une liste dans la classe Scheduler, qui à son tour devrait essentiellement garder la trace d'un compteur de temps et d'appeler la fonction de chaque tâche lorsque le temps arrive. Ces tâches doivent être créés par les objets de la simulation.

Si vous avez besoin d'aide sur le côté de la simulation discrète, aller de l'avant et modifier la question.

Il y a un livre et d'un cadre appelé DEMOS (discrète Modélisation de l'événement sur Simula) qui décrit un cadre fondé sur la co-routine (dêmos éponyme). En dépit d'être 30 ans ou si vieux DEMOS est en fait tout à fait un bon système, et Graham Birtwistle est un gars vraiment sympa.

Si vous implémentez co-routines sur C ++ (pensez setjump / longjump), vous devriez jeter un oeil à ce livre pour une description d'un vraiment, vraiment élégant Cadre de modélisation d'événements discrets. Bien qu'il soit 30 ans, il est un peu un classique intemporel et a encore une base de fans.

Dans le document lié par "me.yahoo.com / ..." qui décrit la classe task.h:

  1. Tâches exécutent en parallèle
  2. Une tâche peut être suspendue et reprise plus tard

La bibliothèque est décrit comme un procédé de multiprogrammation.

Est-il possible de le faire sans utiliser des fils ou des processus séparés?

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