afficher >><< masquer ]
SAMPI - Editeur structuré
1. Le Problème et la Proposition
2. Le Langage Primitif de Représentation Textuelle
2.1. Présentation de la Syntaxe Concrète
2.2. Notations
2.3. Exemple de structuration des données
2.4. Exemple de structuration des traitements
2.4.1. La pile
2.4.2. Les lecteurs-écrivains
2.4.22.1. La spécification du problème
2.4.22.2. La réalisation du problème
2.4.22.3. La spécification des ressources doubles
2.4.22.4. La réalisation des ressources doubles
2.4.3. La racine carrée
2.5. Exemple de structurations connexes
3. Le Langage Complété pour la Structuration des Textes
3.1. Présentation de la Syntaxe Complétée
3.2. Etude quantitative de l'évolution des programmes
3.3. L'édition syntaxique
3.4. étude de cas : le langage LTR3 et l'atelier ENTREPRISE
4. L'Enrichissement du Langage par de Nouveaux Concepts
4.1. Présentation de la Syntaxe Abstraite
4.2. Les difficultés
4.3. Compléter la Syntaxe
5. La Formalisation des Solutions Techniques
5.1. L'évaluation fonctionnelle
5.2. La structuration par les objets
5.3. Modèle sémantique comparé de l'évaluateur
5.4. Comparaison critique
5.5. Construction de la Syntaxe Abstraite
6. Les Comparaisons avec d'autres Approches
7. Les Perspectives
8. Les Editeurs
8.0. brisé sur la barrière de la complexité (une fois de plus)
8.1. L'éditeur ligne : Manuel de l'utilisateur
8.2. L'éditeur page : Guide de l'utilisateur
9. Les Aspects d'Implantation
9.1. Contexte d'évaluation
9.2. La Syntaxe Abstraite : Manuel du concepteur
9.3. L'éditeur page : Guide de l'implanteur
Références
Rubrique Perl-Javascript

Les lecteurs-écrivains

Après « l'exemple d'école » des Types Abstraits de données : la pile, on présente « l'exemple d'école » du parallélisme : il s'agit de l'exemple des lecteurs-écrivains, qu'on traite ici avec une priorité égale pour les lecteurs et les écrivains.

1. La spécification du problème

2. La réalisation du problème

3. La spécification des ressources doubles

4. La réalisation des ressources doubles

4. La réalisation des ressources doubles

La réalisation des ressources demande de définir le type ressource-double et les procédures reserve, free et test.

Le type

Un aspect du problème, qui n'est pas apparu sur le réseau de Petri, est l'accès concurrent des procédures aux « variables d'état » de la ressource. Dans un réseau de Petri, le déclenchement d'une transition est « instantané » : la mise à jour du nombre de jetons dans les places concernées est indivisible ; dans une implantation, chaque étape de la mise à jour est différenciée – on a plusieurs instructions – et la mise à jour complète peut être interrompue – du moins si le moniteur est préemptif. Pour réaliser cette indivisibilité du déclenchement on utilise donc une ressource simple, à un point d'entrée unique.

TYPE ressource: RECORD
                   P,Q : integer;
                   c : integer;
                   acces : resource(1);
                END RECORD;

Les procédures

Les procédures ont alors toutes un schéma de construction voisin : pour une ressource double R, on a :

ressource double - réalisation

On pourrait être "tenté" de réaliser ...recommencer... en "entourant" le traitement d'une boucle infinie, qui teste la condition jusqu'à ce qu'elle devienne vraie.

Par exemple :

ressource double - réalisation

On voit tout de suite que la solution ne convient pas, puisqu'on est à l'intérieur du bloc d'accès exclusif de la ressource et donc qu'aucune tâche ne pourra jamais modifier les valeurs des champs de la ressource, ce qui rendrait éventuellement la condition vraie.

D'une façon naturelle, on est alors conduit à placer la boucle infinie "au-dessus" du bloc d'accès exclusif. A chaque itération, on libère puis on réserve à nouveau la ressource d'accès exclusif ; une autre tâche pourra donc se glisser dans l'intervalle (on réalise ici une attente active : pour un fonctionnement correct il faut supposer que la tâche n'est pas super-prioritaire, parce qu'elle ne serait alors jamais interrompue) :

ressource double - réalisation

(1) Dans le contexte de la boucle /boucle/, on peut quitter la boucle par une phrase EXIT.
(2) Dans le contexte du bloc de réservation, un « sortie brutale » (phrases EXIT ou RETURN) est précédée d'une libération de la ressource.

La représentation « textuelle »

A un niveau de détail fin, on pourrait gérer le contexte dans lequel s'effectue la « sortie brutale » d'une boucle : cela nécessite inévitablement de travailler sur les arbres syntaxiques du langage, pour connaître la sémantique des "bouts de code" qu'on manipule (cf. Chapitre 3.3, « L'édition syntaxique »).

A un niveau plus grossier d'analyse du programme, on ne peut pas déduire des contraintes d'ordre contextuel ; en revanche on peut offrir à l'utilisateur le moyen de les exprimer. Cela signifie qu'on ne propose pas un mécanisme de déduction qui construise ou complète le programme mais plutôt un mécanisme de déclaration qui demande à l'utilisateur de réaliser lui-même les déductions mais qui permet aussi d'en conserver la trace.

La boucle qu'on retrouve dans tous les cas permet de décomposer la vue du corps d'une procédure en deux parties :

ressource double - réalisation

Conclusion

L'exemple est simple ; il présente une petite difficulté qu'on résout en prenant soin, à la rédaction du programme, de ne pas oublier le contexte dans lequel on est placé – ici dans une zone d'exclusion mutuelle.

La représentation « textuelle » fournit in extenso le texte source qu'on est assez naturellement conduit à construire. Cependant elle permet aussi de fixer, dans la Représentation Interne du texte source, la contrainte contextuelle qu'on a respectée ; à la relecture du programme, et à plus forte raison à sa correction on se rappellera cette contrainte, parce qu'elle est contenue dans le support même de m'information.

Corps des ressources doubles

BODY OF ressources-doubles;

   PROCEDURE Initialiser( R:INOUT ressource-double; max_reserve,max_free:IN integer );
   BEGIN
      R.P := max_reserve;
      R.Q := max_free;
      R.c := 0;
      free( R.acces );
   END;

   PROCEDURE reserve( R:INOUT ressource-double );
   BEGIN
      WHILE true DO /boucle/
         reserve( R.acces );
         IF R.c<R.P THEN
            incr( R.c );
            free( R.acces );
            EXIT boucle;
         END IF;
         free( R.acces );
      END DO;
   END;

   PROCEDURE test( R:INOUT ressource-double );
   BEGIN
      WHILE true DO /boucle/
         reserve( R.acces );
         IF R.c<R.Q THEN
            NONE;
            free( R.acces );
            EXIT boucle;
         END IF;
         free( R.acces );
      END DO;
   END;

   PROCEDURE free( R:INOUT ressource-double );
   BEGIN
      WHILE true DO /boucle/
         reserve( R.acces );
         IF R.c>0 THEN
            decr( R.c );
            free( R.acces );
            EXIT boucle;
         END IF;
         free( R.acces );
      END DO;
   END;

END BODY;