• Aucun résultat trouvé

Les protocoles

Dans le document The DART-Europe E-theses Portal (Page 117-123)

Cette façon d'utiliser les canaux n'est pas particulièrement avantageuse. Elle ne fait guère économiser d'éléments d'interconnexion et confie le contrôle de la communication au maitre et à ses esclaves. NJN propose une méthode bien plus abstraite de manipulation des canaux à travers les protocoles.

7.2 Les protocoles

Un protocole est constitué d'un ensemble de méthodes qui assurent la gestion abstraite de la communication à travers le canal. Ces méthodes se définissent de la même manière que les méthodes de composants et suivent les mêmes règles d'interconnexions.

Un protocole particulier, le protocole standard, permet de manipuler un canal à la manière d'une variable, par l'intermédiaire des fonctions njn_read() et njn_write().

Il est constitué de trois méthodes qu'il faut redéfinir pour chaque nouveau type de canal : les méthodes read, write et event.

Le modèle structurel - 105 Voici par exemple une nouvelle version du canal ch_master vu précédemment.dohc_int

NJN_DEF_CHANNEL(ch_master){

NJN_EXTENDS(self, "ch_wire");

njn_new(self, "method", "event", NJN_BODY(ch_master_event));

njn_new(self, "method", "read", NJN_BODY(ch_master_read));

njn_new(self, "method", "write", NJN_BODY(ch_master_write));

return NJN_SUCCESS;

}

Le canal est constitué des signaux req et ack de sa classe parent ch_wire. Les trois méthodes du protocole standard disposent d'une implémentation.

La méthode event est un filtre d'évènement utilisé pour implémenter la liste de sensibilité des tâches. Elle renvoie un entier non nul lorsque l'objet qu'elle reçoit en argument correspond à un objet à surveiller. Vis-à-vis d'un maitre, ce sont les évènements en provenance du signal interne d'acquittement ack qui nous intéressent.

NJN_DEF_BODY(ch_master_event){

njn_ref_t ack = njn_get(local, "ack");

njn_ref_t net = dohc_shift(args);

return dohc_int(dohc_is_same(net, ack));

}

La méthode read abstrait la lecture de l'état du canal. Dans notre cas, elle renvoie l'état du signal ack.

NJN_DEF_BODY(ch_master_read){

njn_ref_t ack = njn_get(local, "ack");

return njn_read(ack);

}

La méthode write abstrait l'écriture sur le canal. Pour notre exemple, elle lance une requête en modifiant l'état du signal req.

NJN_DEF_BODY(ch_master_write){

njn_ref_t req = njn_get(local, "req");

njn_ref_t value = dohc_shift(args);

njn_ref_t after = dohc_shift(args);

if (dohc_is_nil(after)) return njn_write(req, value);

else return njn_write(req, value, after);

}

On retrouve bien évidemment les implémentations réciproques côté esclave.

NJN_DEF_CHANNEL(ch_slave){

NJN_EXTENDS(self, "ch_wire");

njn_new(self, "method", "event", NJN_BODY(ch_slave_event));

njn_new(self, "method", "read", NJN_BODY(ch_slave_read));

njn_new(self, "method", "write", NJN_BODY(ch_slave_write));

return NJN_SUCCESS;

}

106 - Chapitre 4

NJN_DEF_BODY(ch_slave_event){

njn_ref_t req = njn_get(local, "req");

njn_ref_t net = dohc_shift(args);

return dohc_int(dohc_is_same(req, net));

}

NJN_DEF_BODY(ch_slave_read){

njn_ref_t req = njn_get(local, "req");

return njn_read(req);

}

NJN_DEF_BODY(ch_slave_write){

njn_ref_t ack = njn_get(local, "ack");

njn_ref_t value = dohc_shift(args);

njn_ref_t after = dohc_shift(args);

if (dohc_is_nil(after)) return njn_write(ack, value);

else return njn_write(ack, value, after);

}

Pour exploiter le canal, il suffit alors d'appeler les méthodes classiques njn_read() et njn_write() utilisées pour manipuler les variables.

NJN_DEF_COMPONENT(master){

njn_ref_t ch = njn_new(self, "ch_master", "ch", NJN_OUTPUT);

...

njn_new(self, "rt_task", "s", NJN_ALWAYS(master_s),

NJN_TIMESLOT(1 SEC, 0, 100 MSEC));

njn_new(self, "rt_task", "r", NJN_ALWAYS(master_r), NJN_WHEN(ch));

return NJN_SUCCESS;

}

NJN_DEF_ALWAYS(master_s){

njn_ref_t ch = njn_get(local, "ch");

...

Le modèle structurel - 107

Figure 43. Un canal.

Les éléments internes du canal deviennent invisibles à son utilisateur. Il n'est plus utile de leur connecter quoi que ce soit. Le canal se comporte de la même façon qu'une variable à ceci près qu'il peut mettre en œuvre des échanges de données complexes et surtout bidirectionnels.

D'autres protocoles peuvent être construits. Ils devront s'appuyer sur les objets méthodes et sur les fonctions d'API associées : njn_call() et njn_get_return(). En effet, NJN ne permet pas de les prendre en charge de façon totalement transparente.

*

* *

Les nombreux objets d'NJN permettent au modèle structurel de couvrir une grande variété d'approches. Il est principalement orienté composants ce qui facilite la réutilisation du code et permet de construire des applications à partir de composants de bibliothèques. D'ailleurs, la plupart des applications n'exploiteront que les objets les plus simples : composants, tâches et variables. Il convient également aux approches orientées service grâce à des objets tels que les méthodes. Mais la véritable originalité de ce modèle réside plus dans ses propriétés dynamiques, propriétés qui font l'objet du prochain chapitre.

Une remarque en guise de transition : le modèle structurel d'NJN comporte un type d'objets dont nous n'avons pas encore parlé : il s'agit des vecteurs. Ils sont à la base des capacités dynamiques génériques des applications. Pour cette raison, nous avons préféré les présenter dans le chapitre suivant.

C HAPITRE 5

C ONSTRUCTION DES OBJETS ,

DISTRIBUTION ET GESTION DYNAMIQUE DE L ' APPLICATION – L E MODÈLE DE

RECONFIGURABILITÉ ET LE MODÈLE DE DISTRIBUTION

La structure d'une application NJN n'est pas nécessairement figée. Le modèle de reconfigurabilité permet, partant d'une page blanche, de construire une application, de la modifier, d'en adapter les paramètres, etc., pendant que la plateforme est en fonctionnement, sans qu'il ne soit jamais nécessaire d'en arrêter l'exécution. De même, le modèle de distribution permet d'ajuster dynamiquement, en cours d'exécution, la répartition de charges entre les différentes cibles de l'application.

Concernant la reconfigurabilité, deux grandes approches sont proposées par NJN.

La première est assez rudimentaire. L'API fournit les fonctions nécessaires pour créer des composants, les détruire, interconnecter des variables entre elles, configurer les paramètres des tâches, etc. La seconde repose sur la notion de vecteur d'objets et permet de décrire des structures répétitives qu'NJN va pouvoir adapter automatiquement aux besoins de l'application.

Quoi qu'il en soit, tout commence par un modèle d'objet disponible dans une bibliothèque. NJN fabrique en effet les objets de l'application à partir de modèles.

Les modèles sont rangés dans des paquetages et les paquetages sont compilés dans

110 - Chapitre 5

des bibliothèques. La première opération effectuée par NJN lorsqu'il démarre est de charger les bibliothèques dont il a besoin.

La première partie de ce chapitre explique les mécanismes de création d'objet et la manière dont sont organisés les modèles. La seconde porte sur les mécanismes de reconfigurabilité dynamiques standards. Dans la troisième partie, nous aborderons les structures génériques et les vecteurs. Enfin dans la dernière partie sera traité le modèle de distribution.

1 La construction des objets, les paquetages et les bibliothèques

Comme nous l'avons dit dans l'introduction, tout commence avec un modèle.

Dans le document The DART-Europe E-theses Portal (Page 117-123)