Génie logiciel et design de systèmes temps



Documents pareils
4. Outils pour la synchronisation F. Boyer, Laboratoire Lig

Introduction à la programmation concurrente

4. Outils pour la synchronisation F. Boyer, Laboratoire Sardes

LOG4430 : Architecture et conception avancée

Problèmes liés à la concurrence

Un ordonnanceur stupide

On appelle variable condition une var qui peut être testée et

Info0604 Programmation multi-threadée. Cours 5. Programmation multi-threadée en Java

Cours de Systèmes d Exploitation

J2SE Threads, 1ère partie Principe Cycle de vie Création Synchronisation

Threads. Threads. USTL routier 1

Cours 2: Exclusion Mutuelle entre processus (lourds, ou légers -- threads)

Introduction : les processus. Introduction : les threads. Plan

Exercices INF5171 : série #3 (Automne 2012)

Exclusion Mutuelle. Arnaud Labourel Courriel : arnaud.labourel@lif.univ-mrs.fr. Université de Provence. 9 février 2011

Synchro et Threads Java TM

Les processus légers : threads. Système L3, /31

Instructions pour mettre à jour un HFFv2 v1.x.yy v2.0.00

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

Processus! programme. DIMA, Systèmes Centralisés (Ph. Mauran) " Processus = suite d'actions = suite d'états obtenus = trace

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Surveillance de Scripts LUA et de réception d EVENT. avec LoriotPro Extended & Broadcast Edition

Génie Logiciel avec Ada. 4 février 2013

INITIATION AU LANGAGE JAVA

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Exécutif temps réel Pierre-Yves Duval (cppm)

Systèmes d exploitation Gestion de processus

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Notion de thread (1/2)

Once the installation is complete, you can delete the temporary Zip files..

Application Form/ Formulaire de demande

RULE 5 - SERVICE OF DOCUMENTS RÈGLE 5 SIGNIFICATION DE DOCUMENTS. Rule 5 / Règle 5

Temps Réel. Jérôme Pouiller Septembre 2011

Instructions Mozilla Thunderbird Page 1

TD2 Programmation concurrentielle

Archived Content. Contenu archivé

Supervision et infrastructure - Accès aux applications JAVA. Document FAQ. Page: 1 / 9 Dernière mise à jour: 15/04/12 16:14

Bases de programmation. Cours 5. Structurer les données

INTRODUCTION À LA PROGRAMMATION CONCURRENTE

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

M2-Images. Rendu Temps Réel - OpenGL 4 et compute shaders. J.C. Iehl. December 18, 2013

POLICY: FREE MILK PROGRAM CODE: CS-4

Noyau de concurrence par moniteur pour Java ou C# pour une autre sémantique plus fiable et plus performante

Exercices sur SQL server 2000

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

APPENDIX 2. Provisions to be included in the contract between the Provider and the. Holder

Contents Windows

Introduction aux systèmes temps réel. Iulian Ober IRIT

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Programmer en JAVA. par Tama

that the child(ren) was/were in need of protection under Part III of the Child and Family Services Act, and the court made an order on

TD2/TME2 : Ordonnanceur et Threads (POSIX et fair)

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Conventions d écriture et outils de mise au point

Introduction aux Systèmes et aux Réseaux

Frequently Asked Questions

Premiers Pas en Programmation Objet : les Classes et les Objets

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

TABLE DES MATIERES A OBJET PROCEDURE DE CONNEXION

Une introduction à la technologie EJB (2/3)

IFT Systèmes d exploitation - TP n 1-20%

APPENDIX 6 BONUS RING FORMAT

Recherche dans un tableau

MELTING POTES, LA SECTION INTERNATIONALE DU BELLASSO (Association étudiante de lʼensaparis-belleville) PRESENTE :

Temps Réel. Jérôme Pouiller Septembre 2011

DOCUMENTATION - FRANCAIS... 2

Langage propre à Oracle basé sur ADA. Offre une extension procédurale à SQL

Cours Programmation Système

ARCHOS Activity Tracker

Projet gestion d'objets dupliqués

1 Mesure de la performance d un système temps réel : la gigue

GAME CONTENTS CONTENU DU JEU OBJECT OF THE GAME BUT DU JEU

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

DOCUMENTATION - FRANCAIS... 2

Projet de programmation (IK3) : TP n 1 Correction

STS SE. FreeRTOS. Programmation réseau WIFI. Programmation réseau. Socket Tcp. FlyPort smart Wi-Fi module

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Le No.1 de l économie d énergie pour patinoires.

Objets et Programmation. origine des langages orientés-objet

Gestion des transactions et accès concurrents dans les bases de données relationnelles

Les transactions 1/46. I même en cas de panne logicielle ou matérielle. I Concept de transaction. I Gestion de la concurrence : les solutions

France SMS+ MT Premium Description

Les structures de données. Rajae El Ouazzani

Compléter le formulaire «Demande de participation» et l envoyer aux bureaux de SGC* à l adresse suivante :

as Architecture des Systèmes d Information

Programmation MacOSX / ios

Projet Active Object

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

First Nations Assessment Inspection Regulations. Règlement sur l inspection aux fins d évaluation foncière des premières nations CONSOLIDATION

Arbres binaires de recherche

Programmation avec des objets : Cours 7. Menu du jour

Editing and managing Systems engineering processes at Snecma

4. Groupement d objets

Quick Start Guide This guide is intended to get you started with Rational ClearCase or Rational ClearCase MultiSite.

Analyse de sécurité de logiciels système par typage statique

Algorithmique, Structures de données et langage C

Transcription:

Génie logiciel et design de systèmes temps réel H. Mounier 0-0

MOTIVATIONS Utiliser des techniques modernes de conception de logiciel Ceci pour assurer la fiabilité Ces techniques doivent être adaptées au contexte temps réel H.M. Design de systèmes temps réel 1

PLAN DE L EXPOSÉ 1. Guides de design 2. Patrons de conception temps réel 3. Outils de synchonisation, du capteur à l actionneur H.M. Design de systèmes temps réel 2

Guides de design

GUIDES GÉNÉRAUX Faible couplage Un composant ne doit pas se reposer sur les détails internes d un autre. Forte cohésion Un composant doit avoir une définition et un comportement précis et étroit. H.M. Design de systèmes temps réel 3

ENCAPSULATION : PILE BASIQUE EN C Voici un exemple de pile avec comme structure de données interne un tableau #include <stdio.h> #include <stdlib.h> #define TAILLE 200 typedef struct pile { int elements[taille]; /* donnees, ici un tableau */ int *dessus; /* bas de la pile; ne varie pas */ int *dessous; /* haut de la pile; variable */ *pile; pile creer_pile(); void empiler(pile ma_pile, int i); int depiler(pile ma_pile); void detruire_pile(pile ma_pile); H.M. Design de systèmes temps réel 4

ENCAPSULATION : PILE BASIQUE EN C Création de pile pile creer_pile() { pile nouvelle_pile = (pile) NULL; nouvelle_pile = (pile)calloc(1, sizeof(struct pile)); if (nouvelle_pile == (pile)null) { fprintf(stderr, "Creation de pile impossible\n"); perror("message systeme : "); exit(1); /* bas de la pile */ nouvelle_pile->dessous = &(nouvelle_pile->elements)[0]; /* au debut la pile est vide */ nouvelle_pile->dessus = &(nouvelle_pile->elements)[0]; return(nouvelle_pile); /* creer_pile() */ H.M. Design de systèmes temps réel 5

ENCAPSULATION : PILE BASIQUE EN C Empiler une valeur void empiler(pile ma_pile, int i) { (ma_pile->dessus)++; if( ma_pile->dessus == ((ma_pile->dessous) + TAILLE) ) { printf("debordement de pile\n"); exit(1); *(ma_pile->dessus) = i; /* empiler() */ H.M. Design de systèmes temps réel 6

ENCAPSULATION : PILE BASIQUE EN C Dépiler une valeur int depiler(pile ma_pile) { if(ma_pile->dessus == ma_pile->dessous) { printf("assechement de pile\n"); exit(1); (ma_pile->dessus)--; return(*((ma_pile->dessus)+1)); /* depiler() */ H.M. Design de systèmes temps réel 7

ENCAPSULATION : PILE BASIQUE EN C Destruction d une pile void detruire_pile(pile ma_pile) { if (ma_pile == (pile)null) { fprintf(stderr, "Destruction de pile impossible\n"); return; free((void *)ma_pile); /* detruire_pile() */ H.M. Design de systèmes temps réel 8

ENCAPSULATION : PILE BASIQUE EN C Programme principal /** main() **/ void main(void) { int valeur_entree; pile une_pile; une_pile = creer_pile(); do { printf("\t\tentrez une valeur a empiler \n \ (-1 pour sortir, 0 pour depiler) : "); scanf("%d", &valeur_entree); if(valeur_entree!= 0) empiler(une_pile, valeur_entree); else printf("valeur du dessus de pile : %d\n", depiler(une_pile)); while(valeur_entree!= -1); detruire_pile(une_pile); /* main() */ H.M. Design de systèmes temps réel 9

ENCAPSULATION : DISSIMULATION D INFORMATIONS Entre cette partie de code : int pile i, elt_pile; ma_pile; ma_pile = creer_pile(); /* remplissage de la pile */ for(i = 0; i < 100; i++) elt_pile = depiler(ma_pile); où l on utilise depiler() et celle-ci int pile elt_pile; ma_pile; ma_pile = creer_pile(); /* remplissage de la pile */ elt_pile = (ma_pile->elements)[99]; la deuxième solution doit être rejetée. H.M. Design de systèmes temps réel 10

ENCAPSULATION : DISSIMULATION D INFORMATIONS Si l on change la structure de données utilisée pour une pile (par exemple une liste chaînée au lieu d un tableau), la dernière partie de code est désastreuse. L abstraction aide à la maintenabilité et à l intelligibilité en réduisant le nombre de détails à connatre à chaque niveau. La dissimulation d informations aide à la fiabilité (empcher toute opération non autorisée). H.M. Design de systèmes temps réel 11

GUIDES DÉTAILLÉS Pour le faible couplage Minimiser le couplage des méthodes (fonctions) : ne prendre comme entrées que les données nécessaires ; ne renvoyer que les données produites par la méthode Utiliser des hiérarchies appropriées ; par exemple découpage en échelles de temps. Réduit la complexité et accroît donc la fiabilité. Découpler l interface de l implantation (cf. l exemple de la pile) H.M. Design de systèmes temps réel 12

GUIDES DÉTAILLÉS Pour la forte cohésion Chaque composant (chaque méthode) doit avoir un but précis Éviter de passer des données de commande aux méthodes (données décidant comment effectuer les traitements) H.M. Design de systèmes temps réel 13

PATRONS DE CONCEPTION Un patron de conception est une solution éprouvée, constructive à un problème connu. L utilisation de patrons (comme briques de base) permet d accroître la fiabilité (las patrons étant des problèmes déja résolus) H.M. Design de systèmes temps réel 14

PATRONS DE CONCEPTION Exemples de patrons Médiateur, servant à connecter deux composant en introduisant un minimum de couplage. Moniteur, une seule méthode de cet objet peut s exécuter à la fois (accès concurrent). Producteur/consommateur, le producteur peut continuer à produire aussi indépendemment que possible du consommateur Machine à états finis H.M. Design de systèmes temps réel 15

Outils de synchonisation, du capteur à l actionneur

SYNCHRONISATION : MOTIVATION Exemple de mauvaises manières. Deux tâches : capteur qui acquiert des données capteur et loi de commande qui calcule une loi de commande extern int nbsensvals, // indice de lect-ecr ds tampon capteur nbactsvals, // indice de lect-ecr ds tampon actionneur sensorsampletime, // ~ "periode" carte capteur controllawsampletime; // ~ "periode" calcul loi de commande sensordatabuff[sens_buff_size]; // tampon de donnees capteur // methode associee a la thread "capteur" void gathermeasure() { float sensorvalue; // valeur de signal capteur while (1) { // Une valeur de capteur est lue sur la carte associee read(&sensorvalue); // Elle est ecrite dans un tampon capteur sensordatabuff[nbsensvals] = sensorvalue; // On dort un moment sleep(sensorsampletime); H.M. Design de systèmes temps réel 16

SYNCHRONISATION : MOTIVATION // methode associee a la thread "loi de commande" void SensorToActuator(float measure) { float sensorvalue, actuatorvalue; // Valeur d actionneur while(1) { // Lecture du tampon capteur sensorvalue = sensordatabuff[nbsensvals]; // Le prochain echantillon capteur peut etre ecrit if (nbsensvals > SENS_BUFF_SIZE) nbsensvals = 0; else nbsensvals++; // Synthese de la loi de commande actuatorvalue = controllawsynthesis(sensorvalue); // La valeur d actionneur est ecrite dans un tampon actionneur actuatordatabuff[nbactvals] = actuatorvalue; // On dort a nouveau sleep(controllawsampletime); Les variables globales accroissent le couplage H.M. Design de systèmes temps réel 17

SYNCHRONISATION : MOTIVATION L attente active ajustée au moyen de sleep(), très dépendante des fréquences d acquisition capteur et de calcul de loi de commande Le temps de calcul de la loi de commande est très variable (loi linéaire, non linéaire), donc controllawsampletime sera une valeur de pire cas, donc très sous-optimale L utilisation du même indice nbsensvals dans les deux fonctions peut induire divers problèmes Si controllawsampletime > sensorsampletime, la tâche capteur va écraser la même valeur ; Si controllawsampletime < sensorsampletime, la tâche loi de commande va lire des valeurs de capteur très anciennes. H.M. Design de systèmes temps réel 18

SYNCHRONISATION : MOTIVATION Une variable globale, semblerait rǵler les choses extern int nbsensvals, // indice de lect-ecr ds tampon capteur nbactsvals, // indice de lect-ecr ds tampon actionneur sensorsampletime, // ~ "periode" carte capteur controllawsampletime; // ~ "periode" calcul loi de commande littletime; // a small sleep time extern float sensordatabuff[sens_buff_size]; // tampon de donnees capteur extern int lock = 0; // verrou de lecture/ecriture void gathermeasure() { // methode associee a la thread "capteur" float sensorvalue; // Valeur capteur while (1) { // Une valeur de capteur est lue sur la carte associee read(&sensorvalue); if (lock == 0) { // Le verrou a-t-il ete acquis? lock = 1; // Acquerir le verrou sensordatabuff[nbsensvals] = sensorvalue; lock = 0; // Relacher le verrou sleep(sensorsampletime); // Dormir suffisamment longtemps else sleep(littletime); H.M. Design de systèmes temps réel 19

SYNCHRONISATION : MOTIVATION void SensorToActuator(float measure) { de commande" float sensorvalue, actuatorvalue; // associee a "loi // Valeur d actionneur while(1) { if (lock == 0) { lock = 1; // Acquerir le verrou sensorvalue = sensordatabuff[nbsensvals]; if (nbsensvals > SENS_BUFF_SIZE) { nbsensvals = 0; else { nbsensvals++; lock = 0; // Relacher le verrou sleep(controllawsampletime); // Dormir suffisamment longtemps else sleep(littletime); // Synthese de la loi de commande et ecriture dans un tampon actuatorvalue = controllawsynthesis(sensorvalue); actuatordatabuff[nbactvals] = actuatorvalue; H.M. Design de systèmes temps réel 20

SYNCHRONISATION : MOTIVATION Premier problème : Supposons une valeur déja lue par la tâche loi de commande, donc lock == 0. C est un peu plus tard au tour de capteur de s exécuter et elle est après le test. if (code == 0) lorsqu elle est interrompue par loi de commande Cette dernière tâche voit lock égal à 0 et va lire une valeur qui n a pas été écrite. H.M. Design de systèmes temps réel 21

SYNCHRONISATION : MOTIVATION Deuxième problème : Supposons que la tâche capteur soit de plus haute fréquence que la tâche loi de commande Lorsque la tâche capteur a fini de lire une valeur et de la stocker dans un tampon, elle dot dormir suffisamment longtemps ; sinon, elle pourrait reacquérir le verrou lock et lire une autre valeur capteur. Le problème vient du fait que l opération test de lock et mise à 1 de lock n est pas atomique (c.à.d. non interruptible) H.M. Design de systèmes temps réel 22

CONDITION DE COURSE ET SYNCHRONISATION Compétition de plusieurs tâches pour un nombre limité de ressources : condition de course Solution simpliste : Désactiver les interruptions Arrêter l ordonnanceur H.M. Design de systèmes temps réel 23

CONDITION DE COURSE ET SYNCHRONISATION Deux tâches utilisant un verrou de synchronisation doivent être d accord sur le verrou à utiliser pour protéger les données en accès mutuel retreindre au maximum les sections de code critiques (non interruptibles) Ce qui fait défaut ici est une opération atomique de type test and set (tester un mot et le mettre à 1 si ce n est déja fait). int test_and_set(int *lock) { int temp = *lock; *lock = 1; return temp; H.M. Design de systèmes temps réel 24

SÉMAPHORE Structure de base d un sémaphore struct semaphore { int count; // compte du semaphore queue Queue; // liste des taches bloquees par le semaphore Fonction d acquisition de verrou sem wait() sem_wait(semaphore S) { if (S.count > 0) S.count = S.count - 1; else block the task in S.Queue; Fonction d acquisition de verrou sem signal() sem_signal(semaphore S) { if (S.Q is non-empty) wakeup a task in S.Queue; else S.count = S.count + 1; H.M. Design de systèmes temps réel 25

SÉMAPHORE Une autre implantation utilise test and set(), ce qui rend les opérations sem wait() et sem signal() atomique boolean test_and_set(boolean lock) { boolean temp = lock; lock = 1; return temp; Deux fonctions entry() and exit() seront utilisées ; marquage d entrée et de sortie d une tâche dans une section critique // variables partagees par les N tachaes, numerotees 0, 1,..., N-1 boolean lock initially FALSE; boolean waiting[n-1] initially FALSE; // liste des taches en attente entry(int i) { boolean key = FALSE; waiting[i] = TRUE; while (waiting[i] && key) { key = test_and_set(lock); waiting[i] = FALSE; // i est l identificateur de la tache H.M. Design de systèmes temps réel 26

SÉMAPHORE exit(int i) { int p; p = (i+1) mod N; // recherche de la prochaine tache en attente while (p!= i && waiting[p] == FALSE) p = (p+1) mod N; if (p == i) lock = FALSE; // pas de tache en attente else waiting[p] = FALSE; // p est la prochaine tache en attente. La liberer H.M. Design de systèmes temps réel 27

SÉMAPHORE Ces fonctions permettent de résoudre un problème d exclusion mutuelle pour N tâches. Les fonctions sem wait() and sem signal() sont alors sem_wait(semaphore S) { S.entry(i); if (S.count == 0) { S.exit(i); waitin(i, S.Queue); else { S.count = S.count - 1; S.exit(i); // l identificateur de la tache est i waitin(int i, queue Q) { move task i to Q; schedule(); H.M. Design de systèmes temps réel 28

SÉMAPHORE sem_signal(semaphore S) { S.entry(i); if S.Queue not empty move task i to readyqueue; else S.count = S.count + 1; S.exit(i); Ici readyqueue est la queue des tâches prètes à être exécutées. H.M. Design de systèmes temps réel 29

MUTEX Un verrou d exculion mutuelle, ou verrou mutex est un mécanisme de synchronisation partageant certaines des caractéristiques d un sémaphore binaire. Comme pour un sémaphore, il y a des opérations de verrouillage et de déverrouillage, avec blocage sur le verrou déja acquis Contrairement à un sémaphore, un mutex doit être relâché par la tâche qui l a acquise ; il y a une forme de possession du mutex. Deux appels y sont associés : L acquisition du verrou par mutex lock() et La libération du verrou par mutex unlock() H.M. Design de systèmes temps réel 30

VARIABLES DE CONDITION Les variables de condition permettent à une tâche de dormir au sein d une section critique, jusqu à ce qu une expression booléenne définie par le programmeur soit satisfaite. Ce sont des formes d événements associés à un mutex. On utlise la combinaison Un verrou mutex Une expression booléenne Un événement, que d autres tâches peuvent générer pour réveiller la tâche bloquée par la variable de condition Deux appels sont associés à une variable de condition : cond wait() et cond broadcast() H.M. Design de systèmes temps réel 31

VARIABLES DE CONDITION L appel cond wait() apparaît dans une section critique, entre mutex lock() et mutex unlock() L appel cond wait() bloque atomiquement la tâche et relâche le verrou mutex. L appel cond broadcast() relâche le verrou mutex et réveille toutes les tâches bloquées par la variable de condition. H.M. Design de systèmes temps réel 32

Patrons de conception temps réel

MÉDIATEUR Un médiateur est un patron pour affaiblir le couplage entre composants. Le découplage intervient dans le nommage ; les composants n ont besoin de connaître que le médiateur la gestion des données ; on accède aux données uniquement via l interface du médiateur la synchronisation ; toute la synchronisation réside au sein du médiateur Un médiateur est une politique d utilisation du mécanisme offert par le patron moniteur. H.M. Design de systèmes temps réel 33

MONITEUR Un moniteur fournit des méthodes de synchronisation pour accéder aux données La synchronisation est effectuée grâce à un verrou de moniteur. Une seule méthode synchronisée d un moniteur peut s exécuter à la fois. Ces méthodes déterminent quand elles sont bloquées au moyen de conditions de moniteur. H.M. Design de systèmes temps réel 34

MÉTHODES D INTERFACE DU MONITEUR Méthodes d interface (vue externe du moniteur) : put() insère un message dans la file, get() enlève un message de la file empty() et full() testent si la file est vide ou pleine. put() (resp. get()) bloque si la file est pleine (resp. vide). class Message_Queue { public: enum { MAX_MESSAGES = /*... */; ; // The constructor defines the maximum number // of messages in the queue. This determines // when the queue is full. Message_Queue (size_t max_messages = MAX_MESSAGES); // = Message queue synchronized methods. // Put the <Message> at the tail of the queue. H.M. Design de systèmes temps réel 35

MÉTHODES D INTERFACE DU MONITEUR // If the queue is full, block until the queue // is not full. void put (const Message &msg); // Get the <Message> at the head of the queue. // If the queue is empty, block until the queue // is not empty. Message get (void); // True if the queue is full, else false. // Does not block. bool empty (void) const; ; // True if the queue is empty, else false. // Does not block. bool full (void) const; private: //... H.M. Design de systèmes temps réel 36

MÉTHODES D IMPLANTATION DU MONITEUR Méthodes d implantation, qui simplifient le codage des méthodes d interface Découplage synchronisation ordonnancement On utilise les conventions suivantes (idiome de sûreté des thread) : (i) Les méthodes d interface ne font qu acquérir ou relâcher les verrous du moniteur et attendre ou réveiller selon des conditions du moniteur. Elles passent ensuite le contrôle aux méthodes d implantation (ii) Les méthodes d implantation n effectuent aucun appel de synchronisation (ceci est délégué aux méthodes d interface). Ces méthodes ne sont pas bloquantes. H.M. Design de systèmes temps réel 37

MÉTHODES D IMPLANTATION DU MONITEUR Méthodes d implantation : put i() insère un message dans la file get i() enlève un message de la file empty i() et full i() testent si la file est vide ou pleine. Selon l idiome de sûreté des thread, put i() (resp. get i(), empty i(), full i()) est appelée per put() (resp. get(), empty(), full()). H.M. Design de systèmes temps réel 38

MÉTHODES D IMPLANTATION DU MONITEUR class Message_Queue { public: //... See above... private: // = Private helper methods (non-synchronized // and do not block). // Put the <Message> at the tail of the queue. void put_i (const Message &msg); // Get the <Message> at the head of the queue. Message get_i (void); // True if the queue is full, else false. // Assumes locks are held. bool empty_i (void) const; // True if the queue is empty, else false. // Assumes locks are held. bool full_i (void) const; //... H.M. Design de systèmes temps réel 39

ÉTAT INTERNE DU MONITEUR L état interne consiste en 3 groupes Les données représentant la file ; les données elle-même (par ex. un tampon circulaire), et des informations pour déterminer si la file est vide ou pleine (champs message count et max messages ). Les données associées au verrou du moniteur. monitor lock est une instance de Thread mutex défini ci-dessous. Les données associées à la condition du moniteur.les conditions not empty et not full sont utilisées pour bloquer le client si la file est vide ou pleine. Ce sont des instances de Thread Condition défini ci-dessous. H.M. Design de systèmes temps réel 40

ÉTAT INTERNE DU MONITEUR Les classes Thread mutex et Thread Condition sont des instances du patron de facade ( wrapper facade pattern ), c.à.d., ils représentent une interface orientée-object pour les fonctions écrites dans un langage qui ne l est pas (ici le langage C) et sous différents environnements (systèmes d exploitation). class Message_Queue { //... See above... private: // Internal Queue representation.... // Current number of <Message>s in the queue. size_t message_count_; // The maximum number <Message>s that can be // in a queue before its considered full. size_t max_messages_; // = Mechanisms required to implement the // monitor objects synchronization policies. H.M. Design de systèmes temps réel 41

ÉTAT INTERNE DU MONITEUR // Mutex that protect the queues internal state // from race conditions during concurrent access. mutable Thread_Mutex monitor_lock_; // Condition variable used to make synchronized // method threads wait until the queue is no // longer empty. Thread_Condition not_empty_; // Condition variable used to make synchronized // method threads wait until the queue is // no longer full. Thread_Condition not_full_; H.M. Design de systèmes temps réel 42

CLASSE Thread Mutex La classe Thread Mutex est utilisée pour le verrouillage interne du moniteur C est un exemple du patron de facade H.M. Design de systèmes temps réel 43

CLASSE Thread Mutex Voici une implantation sous Solaris: class Thread_Mutex { public: Thread_Mutex (void) { mutex_init (&mutex_, 0, 0); Thread_Mutex (void) { mutex_destroy (&mutex_); int acquire (void) { return mutex_lock (&mutex_); int release (void) { return mutex_unlock (&mutex_); private: // Solaris-specific Mutex mechanism. mutex_t mutex_; // = Disallow copying and assignment. Thread_Mutex (const Thread_Mutex &); void operator= (const Thread_Mutex &); ; H.M. Design de systèmes temps réel 44

CLASSE Thread Mutex Voici une implantation sous Windows NT : class Thread_Mutex { public: Thread_Mutex (void) { InitializeCriticalSection (&mutex_); Thread_Mutex (void) { DeleteCriticalSection (&mutex_); int acquire (void) { EnterCriticalSection (&mutex_); return 0; int release (void) { LeaveCriticalSection (&mutex_); return 0; private: // Win32-specific Mutex mechanism. CRITICAL_SECTION mutex_; // = Disallow copying and assignment. Thread_Mutex (const Thread_Mutex &); void operator= (const Thread_Mutex &); ; H.M. Design de systèmes temps réel 45

CLASSE Thread Mutex Les méthodes ne font qu appeler les fonctions correspondantes du système (d où le nom de patron de facade) H.M. Design de systèmes temps réel 46

CLASSE Thread Condition Lorsque la file est pleine put() doit être bloquante, et lorsqu elle st vide, get() doit être bloquante. Ceci est obtenu en utilisant l implantation de facade Thread Condition class Thread_Condition { public: // Initialize the condition variable and // associate it with the <mutex_>. Thread_Condition (const Thread_Mutex &m) // Implicitly destroy the condition variable. Thread_Condition (void); // Wait for the <Thread_Condition> to be, // notified or until <timeout> has elapsed. // If <timeout> == 0 wait indefinitely. int wait (Time_Value *timeout = 0) const; // Notify one thread waiting on the // <Thread_Condition>. int notify (void) const; H.M. Design de systèmes temps réel 47

CLASSE Thread Condition // Notify *all* threads waiting on // the <Thread_Condition>. int notify_all (void) const; private: #if defined (_POSIX_PTHREAD_SEMANTICS) pthread_cond_t cond_; #else // Condition variable emulations. #endif /* _POSIX_PTHREAD_SEMANTICS */ ; // Reference to mutex lock. const Thread_Mutex &mutex_; H.M. Design de systèmes temps réel 48

TEST DE LA FILE : INTERFACE Voici le code des méthodes d interface empty() et full() bool Message_Queue::empty(void) const { Thread_Mutex_Guard guard(monitor_lock_); return empty_i(); bool Message_Queue::full(void) const { Thread_Mutex_Guard guard(monitor_lock_); return full_i(); Ces méthodes utilisent l idiome de verrou avec portée ( scoped locking idiom ) Le verrou est automatiquement acquis lorsque l on entre en portée (au travers d un constructeur) et est automatiquement relâché lorsque l on est hors de portée (au travers du destructeur correspondant). H.M. Design de systèmes temps réel 49

TEST DE LA FILE : INTERFACE class Thread_Mutex_Guard { public: // Store a pointer to the lock and acquire the lock. Thread_Mutex_Guard (Thread_Mutex &lock) : lock_ (lock) { result_ = lock_.acquire (); // Release the lock when the guard goes // out of scope. Thread_Mutex_Guard (void) { // Only release the lock if it was acquired. if (result_!= -1) lock_.release (); private: // Reference to the lock were managing. Thread_Mutex &lock_; // Records if the lock was acquired successfully. int result_; ; H.M. Design de systèmes temps réel 50

TEST DE LA FILE : IMPLANTATION Voici le code pour les méthodes d implantation empty i() et full i() implementation methods: bool Message_Queue::empty_i(void) const { return message_count_ <= 0; bool Message_Queue::full_i(void) const { return message_count_ > max_messages_; Ces méthodes supposent que le verrou monitor lock a été acquis. Elles ne font que des tests. H.M. Design de systèmes temps réel 51

TEST DE LA FILE : IMPLANTATION void Message_Queue::put (const Message &msg) { // Use the Scoped Locking idiom to // acquire/release the <monitor_lock_> upon // entry/exit to the synchronized method. Thread_Mutex_Guard guard (monitor_lock_); // Wait while the queue is full. while (full_i ()) { // Release <monitor_lock_> and suspend our // thread waiting for space to become available // in the queue. The <monitor_lock_> is // reacquired automatically when <wait> returns. not_full_.wait (); // Enqueue the <Message> at the tail of // the queue and update <message_count_>. put_i (msg); // Notify any thread waiting in <get> that // the queue has at least one <Message>. not_empty_.notify (); // Destructor of <guard> releases <monitor_lock_>. H.M. Design de systèmes temps réel 52

TEST DE LA FILE : IMPLANTATION Le client appelant put() est bloqué jusqu à ce que la file ne soit plus pleine (il est bloqé à not full.wait()). Puis, il transmet à put i() le message qui doit être inséré dans la file. La méthode put i() n a pas besoin d être synchronisée, puisqu elle n est appelée que lorsque le verrou est acquis. Elle n a pas besoin de vérifier non plus si la file est pleine, puisqu elle n est appelée que lorsque full i() renvoie false. De manière similaire à ce qui précède, get() effectue les operations duales H.M. Design de systèmes temps réel 53

TEST DE LA FILE : IMPLANTATION Message Message_Queue::get (void) { // Use the Scoped Locking idiom to acquire/release the // <monitor_lock_> upon entry/exit to the synchronized method. Thread_Mutex_Guard guard (monitor_lock_); // Wait while the queue is empty. while (empty_i ()) { // Release <monitor_lock_> and wait for a new <Message> // to be placed in the queue. The <monitor_lock_> is reacquired // automatically when <wait> returns. not_empty_.wait (); // Dequeue the first <Message> in the queue // and update the <message_count_>. Message m = get_i (); // Notify any thread waiting in <put> that the // queue has room for at least one <Message>. not_full_.notify (); return m; // Destructor of <guard> releases <monitor_lock_>. H.M. Design de systèmes temps réel 54

IMPLANTATION COMPLÈTE L implantation complète est la suivante, sans les commentaires class Message_Queue { public: enum { MAX_MESSAGES = /*... */; ; Message_Queue (size_t max_messages = MAX_MESSAGES); void put (const Message &msg); Message get (void); bool empty (void) const; bool full (void) const; private: private: void put_i (const Message &msg); Message get_i (void); bool empty_i (void) const; bool full_i (void) const; size_t message_count_; size_t max_messages_; mutable Thread_Mutex monitor_lock_; Thread_Condition not_empty_; Thread_Condition not_full_; H.M. Design de systèmes temps réel 55

IMPLANTATION COMPLÈTE class Thread_Condition { public: Thread_Condition (const Thread_Mutex &m) Thread_Condition (void); int wait (Time_Value *timeout = 0) const; int notify (void) const; int notify_all (void) const; private: pthread_cond_t cond_; const Thread_Mutex &mutex_; ; H.M. Design de systèmes temps réel 56

IMPLANTATION COMPLÈTE bool Message_Queue::empty(void) const { Thread_Mutex_Guard guard(monitor_lock_); return empty_i(); bool Message_Queue::full(void) const { Thread_Mutex_Guard guard(monitor_lock_); return full_i(); H.M. Design de systèmes temps réel 57

IMPLANTATION COMPLÈTE bool Message_Queue::empty_i(void) const { return message_count_ <= 0; bool Message_Queue::full_i(void) const { return message_count_ > max_messages_; H.M. Design de systèmes temps réel 58

IMPLANTATION COMPLÈTE void Message_Queue::put (const Message &msg) { Thread_Mutex_Guard guard (monitor_lock_); while (full_i ()) { not_full_.wait (); put_i (new_item); not_empty_.notify (); Message Message_Queue::get (void) { Thread_Mutex_Guard guard (monitor_lock_); while (empty_i ()) { not_empty_.wait (); Message m = get_i (); not_full_.notify (); return m; H.M. Design de systèmes temps réel 59