1
0
mirror of https://gitlab.com/klmp200/LO41.git synced 2024-12-26 17:51:12 +00:00

Correction de fautes dans le rapport

This commit is contained in:
Antoine Bartuccio 2018-06-22 09:34:33 +02:00
parent a6e0aaa089
commit 7310882fde
Signed by: klmp200
GPG Key ID: E7245548C53F904B
2 changed files with 14 additions and 14 deletions

File diff suppressed because one or more lines are too long

View File

@ -7,11 +7,11 @@ Ce sujet de LO41 étant volontairement vague pour permettre de nombreuses implé
Dans un premier temps, nous avons répertorié les contraintes auxquelles nous ne pouvions nous soustraire. C'est donc bien évidemment que nous avons conservé le bâtiment de 25 étages ainsi que les 3 ascenseurs et la borne interactive au pied de ce dernier. C'est à ce moment là que se sont posées les questions les plus importantes et pouvant potentiellement modifier complètement le résultat du projet : est-ce seulement la borne qui permet d'appeler les ascenseurs ? Auquel cas, puisqu'elle est au pied de l'immeuble personne ne peut redescendre autrement qu'en prenant les escaliers. Devons nous utiliser un bouton par ascenseur ou un système d'appel centralisé ? Si on ajoute un bouton pour les ascenseurs à chaque étage, à quoi sert donc la borne au final ? Est-elle uniquement dédiée aux visiteurs ou est-elle utilisable par les résidents ? Est-elle vraiment pertinente ? La rendre indépendante est-il vraiment un choix intéressant ? Allons nous empêcher certains ascenseurs d'accéder à certains étages ou faire en sorte qu'ils aient tous accès à l'entièreté de l'immeuble ? Comment faire pour le dépannage ? Comment peut-on déterminer qu'un technicien est plus à même d'intervenir ? Doit-on avoir plusieurs types de pannes nécessitant différents outils ? Combien tout ceci va-t-il coûter à la copropriété ?
Nous avons donc commencé par trancher sur l'utilisation de la borne. Cette borne aura une utilité assez limitée et sera cantonée à la recherche de l'étage d'un résident par un visiteur. Globalement, elle sera simulée par une fonction renvoyant l'étage d'un résident à partir de son nom. L'appel des ascenseur se fera en interrogeant directement le bâtiment qui se chargera tout seul d'indiquer un ascenseur à partir simplement de l'étage de départ et de l'étage d'arivé souhaité. L'ordonencement des ascenseurs se fera donc directement depuis le bâtiment.
Nous avons donc commencé par trancher sur l'utilisation de la borne. Cette borne aura une utilité assez limitée et sera cantonée à la recherche de l'étage d'un résident par un visiteur. Globalement, elle sera simulée par une fonction renvoyant l'étage d'un résident à partir de son nom. L'appel des ascenseur se fera en interrogeant directement le bâtiment qui se chargera tout seul d'indiquer un ascenseur à partir simplement de l'étage de départ et de l'étage d'arrivée souhaité. L'ordonancement des ascenseurs se fera donc directement depuis le bâtiment.
Nous en arrivons donc logiquement à une distinction visiteurs et résidents. Les visiteurs démarrent à leur étage d'habitation et se déplacent ou non selon leur envie. Les visiteurs, quand à eux, souhaitent rejoindre l'étage d'un résident dont ils connaissent uniquement le nom, ils demandent donc à la borne où celui-ci réside, et tentent d'y accéder en utilisant les ascenceurs.
Enfin, pour les réparations, il a été décidé, afin d'éviter de peser trop fortement sur le budget de la copropriété, d'engager un seul réparateur prêt à répondre à tous les cas pratique et toutes les pannes. Il sera appelé par les ascenceurs qui détecteront automatiquement les pannes et attendront leur réparation selon la disponnibilité de cette ressource critique.
Enfin, pour les réparations, il a été décidé, afin d'éviter de peser trop fortement sur le budget de la copropriété, d'engager un seul réparateur prêt à répondre à tous les cas pratique et toutes les pannes. Il sera appelé par les ascenseurs qui détecteront automatiquement les pannes et attendront leur réparation selon la disponibilité de cette ressource critique.
# Mise en place de l'architecture
@ -20,17 +20,17 @@ Enfin, pour les réparations, il a été décidé, afin d'éviter de peser trop
Dans le cadre de l'UV LO41, nous avons eu l'occasion d'expérimenter et de tester différentes méthodes de parallélisation via l'API du système Linux et UNIX. Nous avons donc dû effectuer un choix crucial : utiliser des processus indépendants ou un seul processus avec plusieurs threads.
Notre choix s'est porté sur l'utilisation de threads et de moniteurs. En effet, ils sont bien plus simples d'usage, puisque toute la mémoire du programme est partagée, permettant une communication efficiente et simple entre les différentes sections indépendantes de celui ci. De plus, en cas d'extinction non contrôlée du programme (particulièrement pratique en phase de tests), il est simple d'opérer vis-à-vis de l'extinction des threads : On évite ainsi tout processus zombie, et donc l'atteinte de la limite maximum de processus système.
Notre choix s'est porté sur l'utilisation de threads et de moniteurs. En effet, ils sont bien plus simples d'usage, puisque toute la mémoire du programme est partagée, permettant une communication efficiente et simple entre les différentes sections indépendantes de celui-ci. De plus, en cas d'extinction non contrôlée du programme (particulièrement pratique en phase de tests), il est simple d'opérer vis-à-vis de l'extinction des threads : On évite ainsi tout processus zombie, et donc l'atteinte de la limite maximum de processus système.
Mais surtout, ce qui a le plus fait pencher la balance en faveur des moniteurs est le fait que cette technologie est présente dans des languages de plus haut niveau tel le java. En effet, on retrouve ce genre de mécanisme directement intégré au language via le mot clef synchronize. C'est ce type de comportement que nous avons souhaité imiter.
Mais surtout, ce qui a le plus fait pencher la balance en faveur des moniteurs est le fait que cette technologie est présente dans des languages de plus haut niveau tel que le java. En effet, on retrouve ce genre de mécanisme directement intégré au language via le mot clef synchronize. C'est ce type de comportement que nous avons souhaité imiter.
## Une architecture orientée objet
En observant le language java, nous avons remarqué qu'une architecture orientée objet, avec son encapsulation, était particulièrement adapté à la parallélisation, et notamment dans le cadre d'utilisation des moniteurs. C'est donc sur ce concept solide et éprouvé que nous avons construit notre projet.
En observant le language java, nous avons remarqué qu'une architecture orientée objet, avec son encapsulation, était particulièrement adaptée à la parallélisation, et notamment dans le cadre d'utilisation des moniteurs. C'est donc sur ce concept solide et éprouvé que nous avons construit notre projet.
Petit problème, nous sommes contraint, de par le sujet, à utiliser le langage C. Ce langage très populaire, inventé en 1972 par Dennis Ritchie, n'est pas pensé pour ce genre d'approche. Il a donc fallu mettre en place bon nombre de stratégies pour rendre cohérente et agréable une approche de programmation non prévue par notre outil. Nous avons poussé le langage dans ses retranchements grâce à de nombreuses macros de manière à modifier la syntaxe selon nos besoins.
Le temps consacré à la mise en place de cette structure est loin d'avoir été perdu et nous a permis de gagner en consistance et en clarté dans notre code. Les fuites de mémoires sont très rares et faciles à régler, le lancement des threads est très simple et ils peuvent être stoppés à tout moment grâce à l'utilisation d'un singleton persistant contenant les différents objets systèmes. Le partage de la mémoire est très simple grâce à une utilisation de getter et setter encapsulant les mutexs. Les interblocages sont quasiment impossilbles à réaliser de cette manière.
Le temps consacré à la mise en place de cette structure est loin d'avoir été perdu et nous a permis de gagner en consistance et en clarté dans notre code. Les fuites de mémoires sont très rares et faciles à régler, le lancement des threads est très simple et ils peuvent être stoppés à tout moment grâce à l'utilisation d'un singleton persistant contenant les différents objets systèmes. Le partage de la mémoire est très simple grâce à une utilisation de getter et setter encapsulant les mutexs. Les interblocages sont quasiment impossibles à réaliser de cette manière.
Voici, pour illustrer, le très concis thread principal de notre programme qui permet d'apprécier à sa juste valeur les modifications apportées à la syntaxe et à l'agencement des structures pour les faire ressembler à des objets :
@ -57,9 +57,9 @@ int main(int argc, char* argv[]) {
## L'introduction des agents
De l'objet à l'agent il n'y a qu'un pas, l'indépendance. Enfin, pas vraiment, mais presque. Nous avons eu l'occasion lors de notre cursus de travailler sur un langage orienté agent : le SARL. Même si celui-ci reste perfectible, il a su nous inspirer lors de la conception de ce projet. Même si nous n'avons pas le temps d'implémenter de la communication entre agent dans des contextes séparés le tout en architecture holonique, nous avons repris l'idée de l'agent et l'avons adaptée à notre architecture et notre projet.
De l'objet à l'agent il n'y a qu'un pas, l'indépendance. Enfin, pas vraiment, mais presque. Nous avons eu l'occasion lors de notre cursus de travailler sur un langage orienté agent : le SARL. Même si celui-ci reste perfectible, il a su nous inspirer lors de la conception de ce projet. Même si nous n'avons pas le temps d'implémenter de la communication entre agents dans des contextes séparés le tout en architecture holonique, nous avons repris l'idée de l'agent et l'avons adaptée à notre architecture et notre projet.
Globalement, il existe 4 types d'agents dans ce projet : les ascenseurs, les visiteurs, les résidents et le casseur d'ascenseur (pour casser les ascenseurs de temps en temps). Ils sont chacun lancés dans leur propre thread et tentent d'atteindre leur objectif indépendament tout en interagissant avec les autres. Ils réagissent également lorsqu'ils reçoivent un signal d'apoptose les invitant à mettre fin à leur existance dans le but de libérer les ressources, dans le cadre d'une fin prévue ou non du programme.
Globalement, il existe 4 types d'agents dans ce projet : les ascenseurs, les visiteurs, les résidents et le casseur d'ascenseur (pour casser les ascenseurs de temps en temps). Ils sont chacun lancés dans leur propre thread et tentent d'atteindre leur objectif indépendamment tout en interagissant avec les autres. Ils réagissent également lorsqu'ils reçoivent un signal d'apoptose les invitant à mettre fin à leur existence dans le but de libérer les ressources, dans le cadre d'une fin prévue ou non du programme.
Pour y parvenir, nous avons attaché à chacun de ces trois objets une méthode `runnable`, qui prend en paramètre une référence vers l'objet lui même et qui configure le thread de manière à répondre de manière normalisée aux signaux. En effet, chaque agent se doit de répondre correctement aux signaux d'apoptose (attachés à SIGUSR1) et d'ignorer les signaux d'arrêt (SIGINT) pour ne pas qu'ils l'interceptent à la place du thread principal puisque la réception de signal dans un environnement multithread n'est pas predictive.
@ -86,7 +86,7 @@ On observe en particulier la singularité de l'objet SharedData, vis-à-vis en t
## Réseau de Pétri
Même si notre architecture initiale limite déjà fortmenet les possiblités d'interblocages, il était judicieux de modéliser de manière abstraite le fonctionnement théorique et basique de l'attente d'un utilisateur à un étage à l'aide d'un réseau de Pétri. La priorité est ici simulée par un nombre d'étape plus ou moins court pour chaque ascenseur. Il faut cependant ne pas oublier que les ascenseurs devant être intelligents et autonomes, il est impossible avec un outil tel que le réseau de pétri de modéliser fidèlement leur comportement. Ce réseau ne donne donc qu'une vision simplifiée du principe et l'implémentation s'en éloigne parfois.
Même si notre architecture initiale limite déjà fortmenet les possibilités d'interblocages, il était judicieux de modéliser de manière abstraite le fonctionnement théorique et basique de l'attente d'un utilisateur à un étage à l'aide d'un réseau de Pétri. La priorité est ici simulée par un nombre d'étapes plus ou moins faible pour chaque ascenseur. Il faut cependant ne pas oublier que les ascenseurs devant être intelligents et autonomes, il est impossible avec un outil tel que le réseau de pétri de modéliser fidèlement leur comportement. Ce réseau ne donne donc qu'une vision simplifiée du principe et l'implémentation s'en éloigne parfois.
![](https://i.imgur.com/nbTpyfB.png)