M4104C-TP-Boost-Exercice6

Exercice donné en test le 06/04/2007

Dans le cours magistral, une implémentation de Boîte Aux Lettres (BAL) a été donnée en utilisant un mutex et une variable condition.

Il a été montré que cette version est fausse ou lourde en présence de plusieurs producteurs et/ou consommateurs.

Une solution consiste à avoir deux files d’attente (= deux variables condition) : l’une pour les consommateurs, l’autre pour les producteurs, et à réveiller sélectivement le thread adéquat.

Travail à effectuer

Créez le projet BALMultiThreadsBoost.

Pour la fin de l’exercice, vous aurez besoin de la fonction Rand().

Modifiez le fichier .pro du projet en conséquence.

Implémentez sur le principe indiqué plus haut la classe C_BALGen d’une boîte aux lettres générique (le “type” de la lettre), ayant pour interface un constructeur, un destructeur, et les deux primitives :

        void Deposer (const T & Val);
        T Retirer (void);

Testez en créant plusieurs producteurs et plusieurs consommateurs qui appellent les fonctions Deposer() et Retirer() avec des périodicités choisies ou aléatoires.

Les affichages doivent faire apparaître quel est le thread qui effectue l’action et quel est le contenu déposé ou retiré de la boîte.

Après quelques essais, vous constaterez sans doute quelques anomalies d’affichage.

Avant de lire la remarque ci-dessous, essayez de les expliquer et reportez-vous à la première partie de l’exécution commentée (plus bas).

Remarque

Les éditions ayant parfois tendance à s’inverser (malgré une exclusion mutuelle), il est intéressant d’ajouter aux opérations un estampillage : le “temps-systeme” doit être récupéré au moment où les opérations de retrait et de dépôt sont effectuées.

Pour cela, vous pouvez récupérer le temps système au moment où les opérations sont effectuées : la fonction de Boost <-- get_system_time() renvoie le temps système de type <-- system_time affichable par l’opérateur d’injection.

Il suffit d’ajouter (provisoirement) un paramètre de ce type aux fonctions Deposer() et Retirer(), et de faire afficher les temps correspondants par chaque producteur/consommateur.

Les affichages 2 et 3 présentés à la suite du paragraphe “Exécution” illustrent ce qu’on appelle la technique d’estampillage.

Exécution

La première ligne correspond à une suite de “mots” lus successivement au clavier.

Le reste du déroulement de programme peut se traduire par la trace suivante :

a z e r t y u i
Prod. 2 a déposé : z Cons. 1 a retiré : z Prod. 1 a déposé : a Cons. 2 a retiré : a
Prod. 2 a déposé : r Cons. 3 a retiré : r Prod. 1 a déposé : e
Cons. 3 a retiré : e Cons. 2 a retiré : t
Prod. 2 a déposé : t Cons. 1 a retiré : y Prod. 1 a déposé : y Cons. 2 a retiré : u
Prod. 2 a déposé : u Prod. 1 a déposé : i
Cons. 3 a retiré : i

Une première anomalie apparaît (cadre rouge) : il semble que deux consommateurs puissent prélever successivement, alors qu’aucun nouveau producteur n’ait produit !

Elle est cependant facile à expliquer : on peut vérifier que les deux consommateurs ne consomment pas la même information.

C’est donc qu’un producteur s’est intercalé entre les deux, mais ce sont les accès en exclusion mutuelle à l’écran qui a inversé les événements.

Une deuxième anomalie apparaît (cadre noir) : les lettres 'a' et 'z', semblent prélevées en ordre inverse de leur apparition dans le flux d’entrée !

Cela se reproduit aussi pour les lettres 'r' et 'e'

En fait, le 'a' a obligatoirement été lu avant le 'z' (cin est un conteneur à accès séquentiel).

Mais le premier thread producteur qui a lu 'a' n’a pas eu le temps de le déposer : le second threadproducteur a lu à son tour 'z' et l’a déposé le premier.

Le premier thread consommateur a donc lu 'z' dans la BAL, etc.

Après ajout de l’estampillage

a z e r t y u i
2008-Nov-19 12:12:51.187172 : Prod. 2 a déposé : z
2008-Nov-19 12:12:51.187547 : Cons. 1 a retiré : z
2008-Nov-19 12:12:52.187153 : Prod. 1 a déposé : a
2008-Nov-19 12:12:52.187329 : Cons. 2 a retiré : a
2008-Nov-19 12:12:55.187577 : Prod. 2 a déposé : r
2008-Nov-19 12:12:55.187752 : Cons. 3 a retiré : r
2008-Nov-19 12:12:57.187359 : Prod. 1 a déposé : e
2008-Nov-19 12:12:59.187873 : Cons. 3 a retiré : e
2008-Nov-19 12:13:03.187792 : Cons. 2 a retiré : t
2008-Nov-19 12:13:03.187782 : Prod. 2 a déposé : t
2008-Nov-19 12:13:04.187567 : Cons. 1 a retiré : y
2008-Nov-19 12:13:04.187556 : Prod. 1 a déposé : y
2008-Nov-19 12:13:08.188564 : Cons. 2 a retiré : u
2008-Nov-19 12:13:08.188553 : Prod. 2 a déposé : u
2008-Nov-19 12:13:11.187859 : Prod. 1 a déposé : i
2008-Nov-19 12:13:11.187991 : Cons. 3 a retiré : i

Remarque : en fait, c’est le premier affichage plus haut qui a été obtenu en supprimant l’estampillage !!!

En effet, rien ne prouve que les messages apparaîtraient dans le même ordre lors d’une seconde exécution !

Après remise en ordre chronologique des messages, les deux dernières anomalies disparaissent et li ne reste que l’inversion des deux premiers caractères, qui ne dépendent pas de la boîte aux lettres mais de l’accès à l’écran.

a z e r t y u i
2008-Nov-19 12:12:51.187172 : Prod. 2 a déposé : z
2008-Nov-19 12:12:51.187547 : Cons. 1 a retiré : z
2008-Nov-19 12:12:52.187153 : Prod. 1 a déposé : a
2008-Nov-19 12:12:52.187329 : Cons. 2 a retiré : a
2008-Nov-19 12:12:55.187577 : Prod. 2 a déposé : r
2008-Nov-19 12:12:55.187752 : Cons. 3 a retiré : r
2008-Nov-19 12:12:57.187359 : Prod. 1 a déposé : e
2008-Nov-19 12:12:59.187873 : Cons. 3 a retiré : e

2008-Nov-19 12:13:03.187782 : Prod. 2 a déposé : t
2008-Nov-19 12:13:03.187792 : Cons. 2 a retiré : t
2008-Nov-19 12:13:04.187556 : Prod. 1 a déposé : y
2008-Nov-19 12:13:04.187567 : Cons. 1 a retiré : y
2008-Nov-19 12:13:08.188553 : Prod. 2 a déposé : u
2008-Nov-19 12:13:08.188564 : Cons. 2 a retiré : u

2008-Nov-19 12:13:11.187859 : Prod. 1 a déposé : i
2008-Nov-19 12:13:11.187991 : Cons. 3 a retiré : i