Multitâche, exclusivité d'accès à une variable [ADA] - Ada - Programmation
Marsh Posté le 04-02-2003 à 16:38:43
Pschitt a écrit : Voila un bout de code qui est censé garantir l'exclusivité d'accès en écriture à une variable mais j'ai du mal à expliquer comment :
|
c'est le select ...end select qui exclut que 2 entrées soient activent en même temps, ce qui veut dire dans ton cas que les lectures sont exclusives entre elles, les écritures sont exclusives entre elles et les lectures sont exclusives par rapport aux écritures et les écritures sont exclusives par rapport aux lectures.
En gros un seul point d'exécution au plus a le droit de se trouver dans un select.
Il existe une solution plus fine à base d'objets protégés, qui t'auraient permis d'avoir des lecture concurrentes et des écritures exclusives.
Marsh Posté le 04-02-2003 à 16:50:33
Exactement. Si mes connaissances Ada ne sont pas trop rouillées, ça devrait donner (attention, Ada 95 only):
Code :
|
Marsh Posté le 04-02-2003 à 22:21:52
Dsls a écrit : Exactement. Si mes connaissances Ada ne sont pas trop rouillées, ça devrait donner (attention, Ada 95 only):
|
pas testé mais rien à redire. C'est même mieux car tu as une fonction qui retourne un résultat pour la lecture et pas un vieux passage de la valeur de retours par effets de bord => plus clair, plus simple.
Marsh Posté le 05-02-2003 à 10:04:46
Vous auriez un lien qui explique les types protégés d'Ada sur le Web ? A part le bon vieux LRM, je n'ai rien trouvé sur AdaHome...
Marsh Posté le 05-02-2003 à 14:28:58
En fait, je ne situais pas comment, dans le code du type protégé de Pschitt, le compilateur Ada pouvait autoriser les appels concurrents à la fonction et pas à la procédure. Dans le code, tien ne les distingue explicitement (à part le fait que l'une est une fonction et l'autre une procédure).
J'ai trouvé ceci cependant pour répondre à ma question :
Citation : Within a protected body we can have a number of subprograms and the implementation is such that (like a monitor) calls of the subprograms are mutually exclusive and thus cannot interfere with each other. A procedure in the protected body can access the private data in an arbitrary manner whereas a function is only allowed read access to the private data. The implementation is consequently permitted to perform the useful optimization of allowing multiple calls of functions at the same time. |
Extrait de cette page : http://www.adaic.com/standards/95r [...] 1-2.html#9
Marsh Posté le 05-02-2003 à 16:02:43
BifaceMcLeOD a écrit : En fait, je ne situais pas comment, dans le code du type protégé de Pschitt, le compilateur Ada pouvait autoriser les appels concurrents à la fonction et pas à la procédure. Dans le code, tien ne les distingue explicitement (à part le fait que l'une est une fonction et l'autre une procédure).
|
C'est la différence classique fonction/procédure :
une fonction est un machin à qui on applique des arguments (0 ou plus arguments) et dont on attend un résultat. Dans certains langages, la machin en question n'a même pas de droit de faire un effet de bord (affectation de variable par exemple), c'est pas fait pour.
Un procédure est une instruction qui une fois exécutée a modifié l'état de l'environement (en changeant la valeur d'une variable, en poussant dans un stream).
Evidement, la plupart des langages mélangent allègrement tout et les déceloppeurs n'ayant jamais eu cette notion clairement enseignée mélangent (par ex. en faisant des procédures avec un paramètre out au lieu d'une fonction sans effet de bords).
D'où la logique du comportement des objets protégés :
les fonction mattent mais ne touchent pas : elles peuvent matter à plusieurs.
les procédures touchent : problème de concurrence -> exclusivité.
Les entries sont en fait des procédures qui peuvent être gardées : la garde est une expression booléenne qui, si elle est fausse au moment de l'appel de l'entry bloquera l'appellant jusqu'à ce qu'elle devienne vraie, sans bloquer les appels de fonction sur l'objet. Si tu avais fait un "wait" en début de procédure, tu aurais perdu la possibilité d'envoyer des appels de fonction sur l'objet pendant l'attente -> ça tient pas la charge.
Marsh Posté le 05-02-2003 à 23:18:30
Mais du coup tu ne peux pas faire de fonction du genre :
function Func returns TheValueType is |
puisque du coup, il y a effet de bord.
Si c'est le cas, je suppose que tu vas me répondre, l'utilisateur n'a qu'à appeler explicitement la procédure d'initialisation, quitte à ensuite lever une exception dans la fonction si tout n'est pas convenablement initialisé...
Marsh Posté le 05-02-2003 à 23:42:14
Citation : |
C'est ça. Dans ton cas bien précis, tu peux faire une procédure avec ta valeur en out, ce qui remplace la fonction et laisse plus transparaître les effets de bord de l'appel. Ou mieux, tu encapsules ton type protégé dans une variable contrôlée, comme ça plus besoin d'appel explicite à Initialize(). Bon par contre coupler type protégé+type contrôlé amène parfois à certaines siouxeries pas évidentes (principalement à cause des types contrôlés d'ailleurs) ... Mais bon, n'est pas fortement typé qui veut
Marsh Posté le 07-02-2003 à 03:18:43
BifaceMcLeOD a écrit : Mais du coup tu ne peux pas faire de fonction du genre :
|
Je ne pense pas que l'utilisateur a à se préocuper de ce genre de détails. Soit la valeur d'initialisation doit être fournie par l'utilisateur et tu te fondes sur une sorte de "construction" avec le discriminant par ex. (piqué du lien plus haut) :
protected type Counting_Semaphore(Start_Count: Integer := 1) is |
Ou alors la valeur par défaut est intrinsèque et donc tu peux la coder en dur :
protected type Counting_Semaphore is |
Je fait part d'une réflection qui m'est venue à l'esprit en cherchant de tête à répondre à ta question (car en réalité on est pas exactement dans le même modèle, ton initialisation est "lazy", fainéante donc à la demande, si elle est coûteuse et a une probabilité importante d'être inutile, c'est un choix. Mon initialisation est "eager", motivée et donc systématiquement exécutée à l'instanciation du type).
Donc je me disait, il suffit d'appeler la procédure d'initialisation de l'objet dans le if : appeller une procédure de type protégé est exclusif, comme on est dans le if, l'exclusivité n'a lieu qu'une fois et tout va bien. Sauf qu'il y a un problème de synchronisation :
2 threads rentrent dans la fonction , rentrent dans le if (c'est les 2 premières) et chacun attend que l'autre se barre de la fonction pour exécuter l'initialisation -> ça peut durer longtemps.
Il doit y avoir moyen de faire plus intelligent, peut-être à base d'entries gardées, mais j'ai pas d'idées.
Marsh Posté le 03-02-2003 à 18:27:28
Voila un bout de code qui est censé garantir l'exclusivité d'accès en écriture à une variable mais j'ai du mal à expliquer comment :
L'explication est elle que tant qu'on est en lecture(LIRE) de la variable V, la tâche ECRIRE étant située également dans le bloc (loop ... end loop) la variable V est protégée en écriture ?