Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • g23beaum/tp-train
  • a23celer/tp-train
2 results
Select Git revision
Show changes
Commits on Source (12)
...@@ -48,3 +48,4 @@ replay_pid* ...@@ -48,3 +48,4 @@ replay_pid*
.DS_Store .DS_Store
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,java # End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,java
/bin/
# TP Train (TP 11 - 15) # TP Train (TP 11 - 15)
_Groupe composé de XXX xxx, YYY yyy._ _Groupe composé de CELERIER Auguste, ACHARD Romain._
## Introduction ## Introduction
Ce projet s'inscrit dans le cadre du cours sur les logiciels concurrents. Il consiste en la modélisation en Java du déplacement de trains sur des rails. Ce projet s'inscrit dans le cadre du cours sur les logiciels concurrents. Il consiste en la modélisation en Java du déplacement de trains sur des rails.
- Éditeur utilisé : `XXX (au choix)` - Éditeur utilisé : Eclipse
## Réponses aux questions ## Réponses aux questions
### Question 1.1 ### Question 1.1
Réponse La classe Position est la plus importante pour gérer le mouvement des trains. En effet, elle contient les information sur l'Element actuel sur lequel le train se situe, et la Direction de son mouvement. La classe Railway gère la liste d'éléments que les trains peuvent parcourir, et permet donc de déterminer le prochain élément sur la trajectoire du train
### Question 1.2 ### Question 1.2
Ouvrir le fichier trains.drawio avec le site https://app.diagrams.net/ Voir fichier trains.drawio
### Question 1.3 ### Question 1.3
etc... Voir code
###Question 2.1
Voir code
###Question 2.2
Les variables qui permettent d'exprimer l'invariant de sûreté sont la présence ou non d'un train dans une section, le nombre de trains présents dans une station et la direction globale des trains sur la ligne
###Question 2.3
Voir code
###Question 2.4
Les actions critiques qu'un train peut exécuter, c'est-à-dire les actions qui modifie l'état du système partagé, sont entrer ou quitter une section, entrer ou quitter une station et changer de direction
###Question 2.5
Ces méthodes doivent être rajoutées respectivement dans Section et Station, et les méthodes de gestion de la direction dans la classe Railway
###Question 2.6
Il faut ajouter des méthodes synchronisées dans les classes Railway et Position pour gérer les mouvements des trains de manière synchronisée, pour autoriser ou non leur déplacement
###Question 2.7
Voir code
### Question 2.8
Voir code
### Question 3.1
Pour éviter les interblocages, on doit contrôler la direction des trains en circulation et leur nombre dans chaque section. On rajoute deux nouvelles variables : `trainsWaitingRL` et `trainsWaitingLR`, qui comptent les trains en attente par direction.
### Question 3.2
L’invariant de sûreté doit garantir qu’un train ne quitte pas une gare si des trains du sens inverse sont déjà en mouvement. Pour cela, un train ne pourra avancer que si aucun train ne se déplace dans le sens opposé. La nouvelle condition qui doit être respectée peut être formulée ainsi :
(currentDirection == d) || (movingTrains == 0)
### Question 3.3
La gestion des interblocages repose principalement sur la classe Railway, qui contrôle la direction des trains, le nombre de trains en déplacement et les trains en attente. C’est dans cette classe que les décisions de départ des trains doivent être prises en fonction de l’état du système. Railway sera donc responsable de la mise en œuvre de la synchronisation et du respect de l’invariant de sûreté.
### Question 3.4
Voir code
### Question 3.5
Voir code
...@@ -20,4 +20,8 @@ public enum Direction { ...@@ -20,4 +20,8 @@ public enum Direction {
return "from right to left"; return "from right to left";
} }
}; };
public Direction turn() {
return this == LR ? RL : LR;
}
} }
...@@ -4,11 +4,8 @@ package train; ...@@ -4,11 +4,8 @@ package train;
* Cette classe abstraite est la représentation générique d'un élément de base d'un * Cette classe abstraite est la représentation générique d'un élément de base d'un
* circuit, elle factorise les fonctionnalités communes des deux sous-classes : * circuit, elle factorise les fonctionnalités communes des deux sous-classes :
* l'entrée d'un train, sa sortie et l'appartenance au circuit.<br/> * l'entrée d'un train, sa sortie et l'appartenance au circuit.<br/>
* Les deux sous-classes sont : *
* <ol> *
* <li>La représentation d'une gare : classe {@link Station}</li>
* <li>La représentation d'une section de voie ferrée : classe {@link Section}</li>
* </ol>
* *
* @author Fabien Dagnat <fabien.dagnat@imt-atlantique.fr> * @author Fabien Dagnat <fabien.dagnat@imt-atlantique.fr>
* @author Philippe Tanguy <philippe.tanguy@imt-atlantique.fr> * @author Philippe Tanguy <philippe.tanguy@imt-atlantique.fr>
......
...@@ -21,7 +21,7 @@ package train; ...@@ -21,7 +21,7 @@ package train;
*/ */
public class Position implements Cloneable { public class Position implements Cloneable {
private final Direction direction; private final Direction direction;
private final Element pos; private Element pos;
public Position(Element elt, Direction d) { public Position(Element elt, Direction d) {
if (elt == null || d == null) if (elt == null || d == null)
...@@ -44,7 +44,38 @@ public class Position implements Cloneable { ...@@ -44,7 +44,38 @@ public class Position implements Cloneable {
public Element getPos() { public Element getPos() {
return pos; return pos;
} }
public void move(Train t, Railway railway) throws InterruptedException {
if (railway == null) {
throw new NullPointerException("Railway cannot be null.");
}
try {
// Get the next element based on the current position and direction
Element nextElement = railway.nextElement(this.pos, this.direction);
if (nextElement instanceof Section) {
((Section) nextElement).enterSection(t, direction, railway);
} else if (nextElement instanceof Station) {
((Station) nextElement).enterStation(t, direction, railway); //On vérifie d'abord si on peut accéder à l'élément suiant
}
if (pos instanceof Section) {
((Section) pos).leaveSection(t, railway);
} else if (pos instanceof Station) {
((Station) pos).leaveStation(t, direction, railway); //On indique ensuite quitter l'élément sur lequel on se trouve
}
this.pos = nextElement; //On modifie l'élement sur lequel le train se trouve
} catch (IllegalArgumentException e) {
// If no next element exists, reverse the direction
this.direction.turn();
}
}
@Override @Override
public String toString() { public String toString() {
StringBuilder result = new StringBuilder(this.pos.toString()); StringBuilder result = new StringBuilder(this.pos.toString());
......
...@@ -10,6 +10,11 @@ package train; ...@@ -10,6 +10,11 @@ package train;
*/ */
public class Railway { public class Railway {
private final Element[] elements; private final Element[] elements;
private Direction currentDirection = null; //Paramètre pour controller la direction actuelle des trains en circulation
private int movingTrains = 0; //Nombre de trains en circulations
private int trainsWaitingRL = 0;
private int trainsWaitingLR = 0;
public Railway(Element[] elements) { public Railway(Element[] elements) {
if(elements == null) if(elements == null)
...@@ -26,11 +31,58 @@ public class Railway { ...@@ -26,11 +31,58 @@ public class Railway {
boolean first = true; boolean first = true;
for (Element e : this.elements) { for (Element e : this.elements) {
if (first) if (first)
first = false; first = false;
else else
result.append("--"); result.append("--");
result.append(e); result.append(e);
} }
return result.toString(); return result.toString();
} }
public Element nextElement(Element currentElement, Direction direction) {
if (currentElement == null || direction == null) {
throw new NullPointerException("Current element or direction cannot be null.");
}
for (int i = 0; i < elements.length; i++) {
if (elements[i] == currentElement) {
if (direction == Direction.LR && i < elements.length - 1) {
return elements[i + 1];
} else if (direction == Direction.RL && i > 0) {
return elements[i - 1];
}
}
}
throw new IllegalArgumentException("Current element is not part of the railway or no next element exists in the given direction.");
}
public synchronized void requestToMove(Train t, Direction d) throws InterruptedException {
// Augmente le nombre de trains en attente
if (d == Direction.LR) trainsWaitingLR++;
else trainsWaitingRL++;
// Attente si un train circule déjà en sens inverse
while (movingTrains > 0 && currentDirection != d ) {
wait();
}
// Réduit le nombre de trains en attente
if (d == Direction.LR) trainsWaitingLR--;
else trainsWaitingRL--;
// Met à jour la direction actuelle
currentDirection = d;
movingTrains++;
}
public synchronized void trainStopped(Train t) {
movingTrains--;
if (movingTrains == 0) {
currentDirection = null; // Réinitialisation de la direction globale quand plus aucun train ne circule
}
notifyAll(); // Réveille les trains en attente
}
} }
...@@ -8,7 +8,36 @@ package train; ...@@ -8,7 +8,36 @@ package train;
* @author Philippe Tanguy <philippe.tanguy@imt-atlantique.fr> * @author Philippe Tanguy <philippe.tanguy@imt-atlantique.fr>
*/ */
public class Section extends Element { public class Section extends Element {
private Train currentTrain = null;
private Direction currentDirection = null;
public Section(String name) { public Section(String name) {
super(name); super(name);
this.currentTrain = null;
this.currentDirection = null;
} }
public synchronized void enterSection(Train t, Direction d, Railway railway) throws InterruptedException {
railway.requestToMove(t, d);
while (currentTrain != null || (currentDirection != null && currentDirection != d)) {
wait();
}
currentTrain = t;
currentDirection = d;
}
public synchronized void leaveSection(Train t, Railway railway) {
if (currentTrain == t) {
currentTrain = null;
currentDirection = null;
notifyAll(); // Réveille les trains bloqués
}
railway.trainStopped(t);
}
} }
...@@ -9,12 +9,36 @@ package train; ...@@ -9,12 +9,36 @@ package train;
* @author Philippe Tanguy <philippe.tanguy@imt-atlantique.fr> * @author Philippe Tanguy <philippe.tanguy@imt-atlantique.fr>
*/ */
public class Station extends Element { public class Station extends Element {
private final int size; private int currentTrain = 0; //nombre de trains présent dans la station
private final int size;
private int trainsGoingLR = 0; // Différenciation des trains selon leur direction
private int trainsGoingRL = 0;
public Station(String name, int size) { public Station(String name, int size) {
super(name); super(name);
if(name == null || size <=0) if(name == null || size <=0)
throw new NullPointerException(); throw new NullPointerException();
this.size = size; this.size = size;
this.currentTrain = 0;
this.trainsGoingLR = 0;
this.trainsGoingRL = 0;
} }
public synchronized void enterStation(Train t, Direction d, Railway railway) throws InterruptedException {
railway.requestToMove(t, d);
while (currentTrain >= size || (d == Direction.LR && trainsGoingRL > 0) || (d == Direction.RL && trainsGoingLR > 0)) {
wait();
}
currentTrain++; // On ajoute le train dans la gare
if (d == Direction.LR) trainsGoingLR++;
else trainsGoingRL++;
}
public synchronized void leaveStation(Train t, Direction d, Railway railway) {
currentTrain--;
if (d == Direction.LR) trainsGoingLR--;
else trainsGoingRL--;
notifyAll(); // Réveille les trains en attente
railway.trainStopped(t);
}
} }
...@@ -42,4 +42,14 @@ public class Train { ...@@ -42,4 +42,14 @@ public class Train {
result.append(this.pos); result.append(this.pos);
return result.toString(); return result.toString();
} }
public void run(Railway railway) {
try {
while (true) {
Thread.sleep(50);
this.pos.move(this, railway);
Thread.sleep(50);
}
} catch (InterruptedException e) {}
}
} }