User Tools

Site Tools


in204:tds:sujets:td8:part2

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
in204:tds:sujets:td8:part2 [2020/11/02 17:00]
bmonsuez
in204:tds:sujets:td8:part2 [2022/11/18 10:49] (current)
Line 1: Line 1:
-====== ​Section critique ​======+====== ​Partie II – Destructeurs ​======
  
-[[in204:​tds:​sujets:​td8|TD8]] +Nous créons les classes suivantes ​:
- +
-===== Références===== +
- +
-[[http://​en.cppreference.com/​w/​cpp/​thread/​unique_lock|std::​unique_lock]] +
-[[http://​en.cppreference.com/​w/​cpp/​thread/​mutex|std::​mutex]] +
- +
-===== Question n°1=====  +
- +
-Nous supposons que nous avons deux fonctions, une première fonction calcule la valeur maximale d’un tableau numérique ​:+
  
 <code cpp> <code cpp>
-void array_find_max( +class GraphicalObject ​
- std::​vector<​int>::​const_iterator begin,  +
- std::​vector<​int>::​const_iterator end, int* theMaxValue)+
 { {
- if (begin != end) +    public: ​       
-+       ​virtual void draw () const ;  
- int result ​*begin+       ~GraphicalObject() { std::cout << "& Delete GraphicalObject \n"} 
- begin++; +       ​ 
- for (; begin != end; begin++) +};
- if (*begin > result) +
- result = *begin+
- *theMaxValue = result; +
- } +
-+
-</​code>​+
  
-la seconde fonction modifie le tableau en multipliant chaque valeur numérique du tableau par 2 :+class Linepublic GraphicalObject  
 +
 +    public: 
 +       ​virtual void draw () const { std::cout << "​Line";​ } ;  
 +       ​~Line() { std::cout << "​Delete Line\n";​ } 
 +        
 +};
  
-<code cpp> +class Circlepublic GraphicalObject ​
-void array_multiply_by( +
- std::​vector<​int>::​iterator begin, +
- std::​vector<​int>::​iterator end, int theValue)+
 { {
- for (; begin != endbegin++) +    public: 
- *begin *= theValue+       ​virtual void draw() const { std::cout << " Circle"​;  
-}+       ~Circle ​ () { std::cout << "​Delete Circle ​ \n"
 +      ​ 
 +};
 </​code>​ </​code>​
  
-Implanter chacune des fonctions. 
  
-<hidden Correction>​ +Nous créons le tableau d’objet suivant :
-Il suffit de recopier les fonctions dans un fichier ''​main.cpp'',​ d'​ajouter l'​inclusion ''​include<​vector>''​ et de compiler. +
-</​hidden>​ +
- +
- +
-===== Question 2 =====   +
- +
-Pour tester les fonctions, nous devons créer des tableaux de taille conséquente. Ces tableaux peuvent-être créés par soit de manière aléatoire soit de manière cycliques. Ci-dessous quelques exemples de fonctions générant des tableaux de taille ''​n''​ et ayant comme valeur des nombres entre ''​0''​ et ''​theMaxValue''​. +
-Nous souhaitons exécuter en parallèle les deux fonctions. ​+
  
 <code cpp> <code cpp>
-void initialize_array(std::​vector<​int>& theArray, ​int theSize+std::​vector<​GraphicalObject*createGraphicalObjects( 
- int theMaxValue)+    ​int theSize)
 { {
- theArray.clear();​ +    std::​vector<​GraphicalObject*>​ graphicalObjects(theSize);​ 
-        theArray.resise(theSize);​ +    for(int i=0; i < size; i++) 
- int step = theMaxValue / 3; +    { 
- theArray[0] = 0; +       ​graphicalObjects[i] = new Line(); 
- for (int i = 1; i < theSize; i++) +       ​graphicalObjects[++i] = new Circle()
- theArray[i] = (theArray[i-1+ step) % (theMaxValue + 1);+    } 
 +    return graphicalObjects;
 } }
 </​code>​ </​code>​
-Ou + 
 +Nous définissons une fonction de dessin pour l'​ensemble des éléments  
 +dans le tableau.
  
 <code cpp> <code cpp>
-#​include<​random>​ 
  
-void initialize_random_array(std::​vector<​int>& ​theArray, int theSize, +void drawGraphicalObjects(std::​vector<​GraphicalObject*>& ​theGraphicalObjects)
- int theMaxValue)+
 { {
- static std::​mt19937 gen(1729); +    for(auto it = theGraphicalObjects.begin();  
- std::​uniform_int_distribution<> distrib(0, theMaxValue);​ +        ​it ​theGraphicalObjects.end(); it++) 
- theArray.clear(); +    { 
- for (int i = 0; i < theSize; i++) +       ​(*it)->​draw(); 
- theArray[i] = distrib(gen);+    }
 } }
 </​code>​ </​code>​
  
  
-<hidden Correction>​ 
- 
-Nous pouvons utiliser pour ce faire une fonction de test du type suivant: 
  
 +Nous créons la fonction de destruction du tableau suivante:
 <code cpp> <code cpp>
  
-void test_valid_execution(std::​vector<​int>& ​theArray)+void deleteGraphicalObjects(std::​vector<​GraphicalObject*>& ​theGraphicalObjects)
 { {
- // Get the max value of the array +    for(auto it = theGraphicalObjects.begin();  
- int referenceMaxValue = *(std::​max_element(theArray.begin(), theArray.end()));+        it < theGraphicalObjects.end(); it++) 
 +    { 
 +       ​delete *it; 
 +    } 
 +
 +</​code>​
  
- // Execute both threads in parallel +Et nous testons avec le code suivant ​:
- int maxValue; +
-        array_find_max(theArray.begin(),​ theArray.end(),​ &​maxValue);​ +
- if (referenceMaxValue != maxValue) +
- std::cout << "Error when computing the max value: " << maxValue << " found, " << referenceMaxValue ​+
  
- array_multiply_by(theArray.begin(),​ theArray.end(),​ 2); +<code cpp>
-        array_find_max(theArray.begin(),​ theArray.end(),​ &​maxValue);​ +
- if (2*referenceMaxValue != maxValue) +
- std::​cout ​<< "Error when computing the max value: " << maxValue << " found, " << 2*referenceMaxValue  +
-}+
  
-int main() +auto graphicalObjects = createGraphicalObjects(10); 
-+drawGraphicalObjects(graphicalObjects); 
- std::​vector<​int>​ array+deleteGraphicalObjects(graphicalObjects);
- initialize_array(array, 10000, 100); +
- test_valid_execution(array); +
-}+
  
 </​code>​ </​code>​
  
-</​hidden>​+===== Question n°1 =====
  
 +Justifier la sortie produite à l’écran ? Est-ce que c’est le comportement désiré ?
  
-===== Question n°3 ===== +<hidden Correction>​
  
-Nous souhaitons ​exécuter les deux fonctions précédents en parallèle+Le destructeur appellé est celui de l'​objet de base. Nous souhaitons ​appeller le destructeur de l'​objet véritablement détruit et non celui de l'​objet de base.
  
-Expliquer pourquoi les résultats ne sont pas toujours cohérents ? ie. que la valeur maximale retournée est supérieure à la valeur maximale du tableau spécifiée au montant de sa création.+</​hidden>​
  
-===== Question ​n°4 ===== +===== Question ​n°2 =====
  
-Il faut utiliser un verrou qui permet à une méthode de se garantir l’exclusivité de l’usage du tableau. Pour ce faire, nous pouvons utiliser un objet std::mutex qui encapsule un mécanisme d’exclusion mutuelle. +Proposer ​une modification pour obtenir ​le comportement souhaité
-L’objet [[http://​en.cppreference.com/​w/​cpp/​thread/​unique_lock|std::​unique_lock]] permet d’obtenir ​un accès exclusif sur un object [[http://en.cppreference.com/​w/​cpp/​thread/​mutex|std::​mutex]]. Quand nous écrivons le code suivant :+
  
-<code cpp> +Tester après cette modification.
-#include <​iostream> ​      // std::cout +
-#include <​thread> ​        // std::​thread +
-#include <​mutex> ​         // std::mutex, std::​unique_lock+
  
-std::mutex mtx;           // mutex fournissant ​le mécanisme d’exclusion mutuelle.+<hidden Correction>​ 
 + 
 +Nous déclarons ​le destructeur dans la classe de base comme étant virtuel.
  
-void my_function (int n, char c) { 
- // section critique, tant que l'​objet lck existe, personne ne pourra 
- // accéder à mtx. 
- std::​unique_lock<​std::​mutex>​ lck(mtx); 
- // Code s'​exécutant. 
-} 
-</​code>​ 
  
-==== Question n°3.1 ====  
-Modifier les fonctions ​ 
 <code cpp> <code cpp>
-int array_find_max(std::vector<int>theArray, int* theMaxValue) +class GraphicalObject  
-</​code>​+
 +    public: ​       
 +       ​virtual void draw () const = 0 ;  
 +       ​~GraphicalObject() { std::cout << "Delete GraphicalObject \n"; } 
 +        
 +};
  
-et +class Line: public GraphicalObject  
 +
 +    public: 
 +       ​virtual void draw () const { std::cout << "​Line";​ } ;  
 +       ​~Line() { std::cout << "​Delete Line\n";​ } 
 +        
 +};
  
-<code cpp> +class Circle: public GraphicalObject ​ 
-void array_multiply_by(std::vector<int>&​ theArray, int theValue)+
 +    public: 
 +       ​virtual ​void draw() const { std::cout << " Circle";​ } ;  
 +       ​~Circle ​ ({ std::cout << "​Delete Circle ​ \n"; } 
 +       
 +};
 </​code>​ </​code>​
-pour implanter le mécanisme d’exclusion mutuelle propose. 
- 
-==== Question n°3.2 ==== 
-Exécuter le code et vérifier que les résultats sont dorénavant cohérents. 
- 
  
 +Désormais, c'est bien le destructeur de l'​objet qui est détruit qui est appellé et pas uniquement le destructeur de la classe de base.
  
 +</​hidden>​
  
in204/tds/sujets/td8/part2.1604336417.txt.gz · Last modified: 2020/11/02 17:00 by bmonsuez