3 Introduction au modèle de programmation DSC pour les composants Salomé
4 ======================================================================
6 Cette introduction a pour objectif de fournir les notions essentielles pour utiliser
7 l'extension DSC (Dynamic Software Component) dans des composants Salomé. Il est
8 destiné aux développeurs d'applications Salomé qui doivent intégrer des codes de
9 calculs sous la forme de composants Salomé ou de services du superviseur.
11 Le principe du modèle de programmation
12 ----------------------------------------
14 Le modèle de programmation DSC est fourni par le noyau Salomé et est disponible
15 non seulement pour les services mais aussi pour des composants Salomé sans supervision.
16 Une application Salomé qui souhaite utiliser l'extension DSC suit toujours ce principe :
18 1. Les différents programmes, codes, services qui composent l'application déclare
19 dans la phase d'initialisation les différents ports disponibles.
20 2. Ensuite le système (par exemple YACS ou un script utilisateur) connecte les
21 différents ports pour mettre en place les différentes communications entre les codes.
22 3. Les codes sont lancés. Lorsqu'ils souhaitent utiliser un de leur port DSC, le code
23 demande au système un pointeur vers son port. Le système vérifie alors que le port
24 a été bien connecté et/ou bien déclaré.
25 4. Les codes utilisent les ports DSC.
27 Apports de l'extension DSC
28 ---------------------------------
30 Les apports principaux de l'extension DSC au modèle de programmation de Salomé sont les
33 1. Il permet de mettre en oeuvre les ports datastream dans Salomé.
34 2. Il permet d'utiliser l'outil de couplage Calcium au sein d'un schéma de calcul sans
35 dépendre de l'implémentation de Calcium hors Salomé. Une meilleure intégration de ce
36 type de ports est ainsi obtenue ainsi qu'une plus grande flexibilité dans les types de
38 3. Il offre la possibilité d'ajouter des ports de type interface dans des services.
40 Les ports de type interface
41 +++++++++++++++++++++++++++++
43 DSC permet d'ajouter des ports de type interface à des composants et donc à des
44 services. Les ports datastream ne sont qu'une spécialisation de ces ports d'interfaces.
45 Cette interface est décrite par le biais d'une interface CORBA. Elle doit donc être
46 implémentée par un objet CORBA qui peut soit être le composant lui même ou un objet que
47 le composant utilise. A chaque port d'interface, des propriétés peuvent lui être
48 attachées grace à un objet spécifique de configuration.
50 Les ports datastream Calcium
51 +++++++++++++++++++++++++++++
53 Le noyau Salomé propose une nouvelle implémentation des ports Calcium. Ces ports
54 sont des ports d'interfaces, ils peuvent donc être utilisés comme les autres ports
55 d'interfaces par le biais de l'API C++ ou ils peuvent être utilisés comme avec Calcium
56 par le biais d'une interface C ou FORTRAN. Enfin, cette nouvelle implémentation a été
57 réalisé avec le soucis de pouvoir porter une application Calcium très rapidement dans
60 Les connexions entre les ports DSC
61 ------------------------------------
63 Les ports DSC peuvent être entrant ou sortant. Les ports sortant sont appelés
64 << uses >> car ils permettent l'utilisation d'une interface externe au composant ou au
65 service. Les ports entrant sont appelés << provides >> car ils fournissent l'implémentation
66 de l'interface du port.
68 Les ports des services sont décrits dans un fichier XML que le gestionnaire de
69 catalogues lit lors de la création d'un schéma de calcul. En revanche les ports ne
70 sont pas décrits dans la déclaration CORBA du service. C'est pourquoi ils sont créés
71 et ajoutés dynamiquement lors de la création et de l'exécution du service (en comparaison
72 avec des modèles plus statiques tel que le CORBA Component Model). DSC ajoute des méthodes
73 aux composants pour déclarer des ports d'interfaces.
77 void add_provides_port(...);
78 void add_uses_port(...);
79 Ports::Port get_provides_port(...);
80 uses_port get_uses_port(...);
82 Des méthodes sont fournies pour permettre la connexion de ports uses avec des ports
83 provides du même type (c'est à dire de la même interface CORBA). De plus, DSC averti
84 le code utilisateur des modifications des connexions des ses ports par le biais de méthodes
89 void connect_provides_port(...);
90 void connect_uses_port(...);
91 boolean is_connected(...);
92 void disconnect_provides_port(...);
93 void disconnect_uses_port(...);
94 void provides_port_changed(...);
95 void uses_port_changed(...);
97 Les connexions entre les ports uses et provides permettent différentes combinaisons. Un port
98 uses peut être connecté à plusieurs ports provides. De même un port provides peut être connecté
99 à plusieurs ports uses. Enfin, les ports uses connaissent les ports provides auxquels ils
100 s'adressent tandis que les ports provides ne connaissent pas à priori les ports uses qui les
101 ont appelés (Il est évidemment possible de rajouter des informations applicatives).
103 Les deux couches de programmation
104 ------------------------------------------------
106 Le modèle de composant DSC est divisé en deux parties : DSC_Basic et DSC_User.
108 DSC_Basic est la couche basse de DSC. Elle fournit les fonctions de bases pour ajouter
109 la notion de ports à un objet CORBA. Elle permet d'enregistrer les servants des ports provides,
110 déclarer des ports uses et les connecter. Il s'agit d'une couche dite basique car elle n'offre
111 que peu de confort d'utilisation. Notamment, un port uses se présente sous la forme d'une
112 séquence de références vers les ports provides auquel le port a été connecté. A charge à
113 l'utilisateur de gérer cette séquence et d'appeler manuellement les différentes ports provides
114 lors de l'utilisation du port uses.
116 La couche DSC_User permet d'obtenir un plus haut niveau de programmation et d'encapsulation
117 des ports. Tout d'abord, elle permet la création de services Salomé avec des ports datastream
118 (ou d'interface) fournis par la plate-forme Salomé. Elle fournit une méthode d'initialisation
119 que le superviseur va appeler avant l'exécution du service, méthode qui permet de déclarer
120 correctement les ports des services. Enfin, elle offre une abstraction pour les ports uses et
121 provides. Les deux types de ports sont implémentés par des classes et l'utilisateur a ainsi
122 une vue uniforme des deux types ports : 2 classes (et non une séquence et une référence CORBA
123 comme dans la couche DSC_Basic). Un autre apport est la gestion automatique de la liste des
124 ports provides connecté à un port uses. Le code utilisateur a une unique référence sur son
125 port uses; à charge à l'implémentation du port uses de transmettre un appel vers les
126 différentes connexions du port.
129 ------------------------------------------------
131 Nous allons maintenant découvrir les principes de la programmation DSC par le biais de
134 Le premier exemple met en place un composant avec un port provides.
135 Le deuxième exemple met en place un deuxième composant avec un port uses qui va être
136 connecté au port provides de l'exemple Hello World.
137 Le troisième exemple montre comment utiliser les ports datastream dans des services.
138 Le quatrième exemple montre comment utiliser le système de fabrique des ports datastream
139 pour ajouter sa propre famille dans le modèle de programmation.
140 Enfin le cinquième exemple montre comment utiliser la nouvelle implémentation Calcium dans le
143 Les exemples ci-dessous montre des exemples de programmation des composants. En revanche,
144 ils ne contiennent pas tout le code, seule les nouvelles parties seront décrites dans ce
145 document. Vous pourrez trouver tout le code des exemples dans le module Salomé DSC_EXEMPLE_SRC.
147 Les deux premiers exemples ont pour objectif de faire comprendre comment manipuler des ports
148 DSC par le biais de la couche DSC_Basic. En revanche, il faut étudier le troisième exemple
149 pour pouvoir créer des services avec des ports DSC par le biais de la couche DSC_User.
151 Pour récupérer les exemples, il faut être autoriser à accéder à la base subversion du projet pal.
152 Il suffit ensuite dans un shell unix de taper la ligne suivante :
154 svn co svn://<nom>@nepal/PAL/DSC_EXEMPLES_SRC/trunk DSC_EXEMPLES_SRC
159 Les sources de cet exemple se trouve dans le répertoire src/Ex_Serveur.
161 L'objectif de cet exemple est de créer un composant qui fournit un port provides.
162 La figure ci-dessous illustre ce que nous allons faire. Le composant s'appelle Ex_Serveur
163 et il fournit un port provides nommé Ex_Hello. Ce port provides fournit l'interface HelloWorld.
165 .. image:: images/progdsc_img1.png
167 La première étape est de définir les interfaces du composant et l'interface du port :
171 Interface HelloWorld : Ports::Port {
172 void say_hello(in string name);
175 Interface Ex_Serveur : Engines::DSC {};
177 Le fichier IDL comprend tout d'abord la déclaration de l'interface du port provides que
178 le composant va fournir. Il s'agit ici de l'interface HelloWorld. Cette interface est une
179 interface CORBA classique. En revanche, cette interface doit hériter de Ports ::Port pour
180 pouvoir être un port DSC. Le composant Ex_Serveur est aussi déclaré comme une interface CORBA
181 qui hérite de l'interface Engines::DSC au lieu de Engines::Component. Il faut noter que le port
182 provides n'apparaît pas dans la définition IDL du composant. Le port est ajouté et déclaré
183 dans les sources de l'implémentation du composant. Il est ajouté dynamiquement lors de
184 l'exécution du composant.
186 Il s'agit maintenant d'implémenter le composant et le port provides. Le port provides est
187 implémenté par le biais d'une classe C++ que nous appellerons HelloWorld_impl (voir dans
188 les sources). Cette implémentation ne diffère en rien de celle d'un objet CORBA. Voici
189 l'implémentation de la méthode say_hello :
194 HelloWorld_i::say_hello(const char * name) {
195 std::cout << "Hello " << name << " ! " << std::endl;
199 Il nous reste ensuite à implémenter le composant. Nous allons nous intéresser à la déclaration
200 du port du composant et à la classe que le composant doit hériter. L'implémentation d'un
201 composant (classe Ex_Serveur_i) qui veut utiliser des ports DSC doit hériter de la classe nommé
202 Engines_DSC_i.. Bien entendu, elle doit aussi hériter de POA_Ex_Serveur.
203 Voici la déclaration de la classe Ex_Serveur_i :
208 public Engines_DSC_i,
209 public POA_Ex_Serveur
213 Ex_Serveur_i(CORBA::ORB_ptr orb,
214 PortableServer::POA_ptr poa,
215 PortableServer::ObjectId * contId,
216 const char * instanceName,
217 const char * interfaceName);
219 virtual ~Ex_Serveur_i();
223 Pour que le port provides soit utilisable, nous devons faire deux actions :
225 - Enregistrer le port dans le composant.
227 Pour réaliser ces deux étapes, nous ajoutons une méthode à la classe Ex_Serveur_i nommée
228 register_ports() qui est appelé dans la fabrique du composant avant que celle-ci ne retourne
229 la référence du composant au container. Cette méthode est implémentée de la façon suivante :
234 Ex_Serveur_i::register_ports() {
236 // Création du port provides
237 _Ex_Hello_port = new HelloWorld_i();
238 _Ex_Hello_port_properties = PortProperties_i();
240 // Enregistrement du port provides
241 add_provides_port(_Ex_Hello_port->_this(),
243 _Ex_Hello_port_properties->_this());
246 La méthode commence par la création du port provides. Il s'agit ici de créer le servant de
247 l'interface CORBA du port. Il faut aussi créer un objet pour les propriétés du port. Dans
248 cet exemple, l'objet par défaut est utilisé (fourni par le noyau). Ensuite le port est
249 enregistré dans le composant par le biais de la méthode add_provides_port fourni par DSC.
251 Le fait d'hériter de Engines_DSC_i oblige le composant à implémenter deux méthodes qui se
252 nomment provides_port_changed() et uses_port_changed(). Ces deux méthodes sont des callbacks
253 que le système utilise pour avertir le composant lorsque les connexions de ses ports ont
254 évolués. La méthode provides_port_changed() permet d'être averti lorsque quelqu'un se connecte
255 ou se déconnecte sur un de ses ports provides. Le callback indique notamment combien de
256 client utilise le port provides (argument connection_nbr). Pour cet exemple, nous ne tenons
257 pas compte de cette information. La méthode uses_port_changed() a quand à elle la même
258 fonction que provides_port_changed(), mais pour les ports uses. Nous verrons dans le deuxième
259 exemple ses spécificités.
261 La documentation des différentes méthodes Engines_DSC_i sont fournis dans la documentation
262 Doxygen du noyau de Salomé.
264 Cet exemple peut être exécuté par le biais du fichier de test src/tests/test_Ex_Serveur.py
265 dans l'intrepréteur Salomé en mode terminal. Ce script illustre l'utilisation des ports DSC :
269 import LifeCycleCORBA
272 import HelloWorld_idl
274 lcc = LifeCycleCORBA.LifeCycleCORBA()
275 component = lcc.FindOrLoad_Component('FactoryServer', 'Ex_Serveur')
276 hello_port = component.get_provides_port("Ex_Hello", 0)
277 hello_port.say_hello("andre")
279 Après la création du composant par le biais du LifeCycleCORBA, le script utilise la
280 méthode get_provides_port pour obtenir une référence sur le port provides du composant.
281 La référence obtenue est ensuite utilisée pour exécuter la méthode say_hello du port.
284 +++++++++++++++++++++
286 Les sources de cet exemple se trouve dans le répertoire src/Ex_Client et dans src/Ex_Serveur.
288 L'objectif de cet exemple est de créer un nouveau composant qui va utiliser le port Ex_Hello
289 du précédent exemple par le biais d'un port uses.
291 Voici une figure qui représente l'application:
293 .. image:: images/progdsc_img2.png
295 Le composant Ex_Client est décrit comme le composant Ex_Serveur dans le fichier IDL.
296 La seule différence est l'ajout dans son interface d'une méthode start(). Un composant
297 ne contenant pas de fonction main lors de sa création, il nous faut une méthode pour lancer
298 l'exécution du composant, d'où la définition de la méthode start.
300 Voici la définition IDL du composant Ex_Client :
304 Interface HelloWorld : Ports::Port {
305 void say_hello(in string name);
308 Interface Ex_Serveur : Engines::DSC {};
310 Interface Ex_Client : Engines::DSC {
314 Il faut maintenant implémenter le composant. Comme pour un port provides, un port uses
315 doit être enregistré dans le composant avant qu'il ne soit utilisable par le composant.
316 Un port uses correspond à une séquence de références vers les ports provides auxquels il
317 a été connecté ; c'est pourquoi il n'est pas implémenté par une classe comme un port
318 provides. En revanche, il est toujours possible d'ajouter des propriétés au port.
319 Voici le code de la méthode register_ports() pour le composant Ex_Client :
324 Ex_Client_i::register_ports() {
326 // Création de l'objet propriété pour le port uses.
327 _U_Ex_Hello_port_properties = new PortProperties_i();
329 // Ajout du port uses dans le composant
330 add_uses_port("IDL:HelloWorld:1.0",
332 _U_Ex_Hello_port_properties->_this());
336 Un port uses est associé à un type d'objet CORBA. La déclaration de ce type permet de
337 vérifier si le port uses est connecté à un port provides compatible. Dans cet exemple,
338 le type du port (déclaré dans l'IDL) est HelloWorld. CORBA propose pour chaque type IDL
339 une chaîne de caractère correspondant à ce type. Dans cet exemple il s'agit de :
342 Il faut maintenant pouvoir utiliser le port uses. Pour cela, le composant demande au
343 système de récupérer le port uses par le biais de la méthode get_uses_port(). Le port
344 prend la forme d'une séquence de référence sur les différents ports provides. Les références
345 contenues dans cette séquence sont les ports provides auxquels le port uses a été connecté
346 à l'instant de l'appel de la méthode get_uses_port(). A chaque changement sur cette liste
347 de référence, que ce soit un ajout ou un retrait, le système utilise la
348 méthode use_port_changed() pour avertir le code utilisateur.
350 La méthode start() du composant Ex_Client va récupérer le port uses U_Ex_Hello et va
351 appeler la méthode say_hello() sur la première référence. Voici le code de cette méthode :
356 Ex_Client_i::start() {
358 // Récupération du port ues U_Ex_Hello
359 Engines::DSC::uses_port * uport = get_uses_port("U_Ex_Hello");
361 // Récupération de la première référence de la séquence
362 _Ex_Hello_provides_port = HelloWorld::_narrow((* uport)[0]);
364 // Appel de la méthode sur le port
365 _Ex_Hello_provides_port->say_hello(_instanceName.c_str());
368 Il faut noter qu'il faut transformer par le biais de la méthode _narrow les références
369 contenues dans le port uses dans le type du port provides pour pouvoir utiliser le port provides.
371 Ports datastream et services
372 ++++++++++++++++++++++++++++++
374 Les sources de cet exemple se trouve dans le répertoire src/Ex_ProducteurConsommateur.
376 L'objectif de cet exemple est double. Tout d'abord, l'exemple montre comment mettre en
377 oeuvre un service qui veut utiliser des ports DSC. Ensuite, il montre comment utiliser
378 les ports datastream inclus dans le noyau de Salomé.
380 Cet exemple met en place deux services qui vont être connectés par un port datastream.
381 Le service produit du composant Producteur va produire un flux de donnée, et le composant
382 consomme du composant Consommateur va afficher des données.
384 Le service produit se termine lorsqu'il a envoyé toutes les données qu'il doit produire.
385 Le nombre de données à produire est déterminé par le port dataflow nombre. Le service
386 consommateur a quand à lui besoin de connaître combien de données il doit récupérer avant
387 de se terminer. Ce nombre est, comme pour le service produit, déterminé par le port dataflow
390 Voici la définition IDL des deux composants :
394 interface Producteur : Engines::Superv_Component {
395 void produit(in long nombre);
398 interface Consommateur : Engines::Superv_Component {
399 void consomme(in long nombre);
402 Pour déclarer un composant qui va contenir des services utilisant des ports DSC, le composant
403 doit hériter de l'interface Engines::Superv_Component et non plus de l'interface
404 Engines::Component. En plus d'ajouter au composant l'interface de DSC,
405 Engines::Superv_Component ajoute la méthode init_service() qui est appelé par le
406 superviseur avant l'exécution du service. L'objectif de cette méthode est de permettre au
407 concepteur du service d'initialiser les ports du service en vu de leur connexion avant le
408 lancement effectif du service. Par rapport aux exemples précédents, init_service() a la même
409 fonction que register_ports().
411 Il s'agit maintenant d'implémenter ces deux composants. La première différence avec un
412 composant classique est qu'il faut hériter de la classe Superv_Component_i. De plus, il
413 faut implémenter la méthode init_service().
415 Voici l'implémentation de la méthode init_service du composant Producteur :
420 Producteur_i::init_service(const char * service_name) {
421 CORBA::Boolean rtn = false;
422 string s_name(service_name);
423 if (s_name == "produit") {
424 add_port("BASIC_short", "uses", "produit_port");
430 La couche DSC_User qui implémente la classe Superv_Component_i fournit de nouvelles méthodes
431 pour l'ajout des ports uses et provides. Il s'agit des méthodes de la famille add_port (Voir
432 la documentation doxygen de Salomé). Ces méthodes ont pour objectif de permettre la création
433 et l'enregistrement d'un port du service en une seule étape. De plus, elles permettent
434 d'utiliser les ports datastream prédéfinis dans le noyau Salomé.
436 Dans le cas du service produit, nous avons choisi d'utiliser le port datastream BASIC_short.
437 Lorsque le noyau Salomé fournit un port datastream, il fournit toujours l'implémentation pour
438 le port provides et pour le port uses. La première partie du nom (BASIC) identifie la famille
439 de port datastream (comme CALCIUM ou PALM par exemple). La deuxième partie du nom contient le
440 type de donnée transmis, dans cet exemple, un short. Ce type de port constitue le premier
441 paramètre de la méthode add_port. Les deux autres arguments sont le type de port DSC (uses ou
442 provides) et le nom du port dans le composant.
444 Lorsqu'il va s'agir d'utiliser ce port dans le service, il va falloir, comme dans les exemples
445 précédent, récupérer une référence sur le port. Pour cela de nouvelles méthodes nommées
446 get_port sont disponibles (à l'image des add_port). Voici un exemple de code pour utiliser
447 la méthode get_port :
451 uses_port * my_port = NULL;
452 get_port(my_port, "produit_port");
453 if (my_port != NULL) {
454 for (CORBA::Long i = 0; i < nombre; i++) {
455 data_short_port_uses * the_port = dynamic_cast<data_short_port_uses * >(my_port);
460 La méthode get_port a deux arguments. Le premier va contenir un pointeur vers le port et le
461 deuxième indique le nom du port demandé. Après l'appel de la méthode get_port, un pointeur
462 générique est obtenu. On change ensuite son type avec le type de port attendu par le biais
463 d'un dynamic_cast. Il est alors possible d'utiliser le port.
465 Pour permettre plus de commodité dans la programmation, la couche DSC_User propose plusieurs
466 signatures pour les méthodes get_port et add_port. Par exemple, le composant Consommateur
467 utilise les versions template de ces méthodes pour l'ajout et la récupération du code.
471 data_short_port_provides * my_port = NULL;
472 my_port = get_port<data_short_port_provides>("consomme_port");
475 for (CORBA::Long i = 0; i < nombre; i++) {
476 cout << "Hello, I receive : " << my_port->get() << endl;
480 La liste des différents types de ports fournis par le Noyau de Salomé est disponible dans
481 la documentation Doxygen du noyau Salomé.
483 Ajouter des ports datastream et/ou d'interfaces
484 +++++++++++++++++++++++++++++++++++++++++++++++++
486 Les sources de cet exemple se trouve dans le répertoire src/Ex_ProducteurConsommateur_Adv.
488 L'objectif de cet exemple est de montrer les mécanismes pour ajouter ces propres types de
489 ports dans la couche DSC_User. Pour cela, cet exemple explique comment remplacer le port
490 BASIC_short de l'exemple précédent par son propre port. Etant donné que cet exemple est
491 quasiment identique au niveau des composants, nous nous intéresserons uniquement dans ce
492 document à la déclaration et l'implémentation du port.
494 Une famille de port Datastream (ou d'interface) contient deux types d'objets différents:
497 2. L'implémentation des ports.
499 La couche DSC_User connaît les types de port Datastream par le biais du design pattern
500 fabrique. Pour chaque famille, une fabrique est enregistrée à la création du composant.
501 Elle est ensuite utilisée par le composant dans les méthodes add_port(...) pour créer et
502 enregistrer les ports.
504 Tout d'abord, il faut déclarer dans un fichier IDL (MesPorts.idl dans l'exemple) son ou ses
511 interface Mon_Type_De_Port : Ports::Data_Port {
512 boolean is_new_data_available();
514 interface Short_Mes_Ports : Mon_Type_De_Port {
515 void put(in short data);
520 Dans cet exemple on déclare un port : Short_Mes_Ports. Il s'agit d'un port qui permet
521 d'envoyer un short, mais également qui peut être interrogé pour savoir si une nouvelle
522 donnée est arrivée. En revanche la méthode get() n'est pas déclaré dans l'IDL (bien que
523 ce soit possible) car elle uniquement destinée à être utilisé en local.
525 Il faut maintenant implémenter le type de port. Pour cela, il faut implémenter la fabrique
526 et la partie uses et la partie provides du type de port.
528 Une fabrique de port est un objet qui implémente l'interface de la classe abstraite
529 port_factory (voir la documentation Doxygen). La fabrique est appelée à chaque fois qu'un
530 service ajoute un port dans le composant (uses ou provides). La fabrique est identifiée par
531 une chaîne de caractère qui l'identifie auprès du composant. L'enregistrement des fabriques
532 doit se faire au plus tôt. C'est pourquoi les fabriques sont enregistrées dans le constructeur
535 La figure suivante montre l'enregistrement de la fabrique dans le composant ProducteurAdv :
539 ProducteurAdv_i::ProducteurAdv_i(CORBA::ORB_ptr orb,
540 PortableServer::POA_ptr poa,
541 PortableServer::ObjectId * contId,
542 const char * instanceName,
543 const char * interfaceName) :
544 Superv_Component_i(orb, poa, contId, instanceName, interfaceName)
547 _id = _poa->activate_object(_thisObj);
549 register_factory("MESPORTS", new mes_ports_factory());
552 Dans cet exemple, le nouveau type de port est identifié par la chaîne MESPORTS. Il faut
553 noter qu'il est interdit d'utiliser le symbole << _ >> dans le nom. En effet, il sert de
554 séparateur entre le nom de la famille et le type du port dans la famille (Ex : MESPORTS_short).
556 Il reste à implémenter les ports. Pour chaque port défini dans l'IDL, il faut implémenter
557 la partie uses port et la partie provides port. L'implémentation côté uses doit hériter de
558 la classe uses_port. Du côté provides, il faut hériter de la classe provides_port.
560 Les classes uses_port et provides_port sont des classes abstraites. Elles proposent des
561 méthodes qui permettent d'automatiser l'enregistrement et la gestion des ports. Dans la couche
562 DSC_Basic, c'est le développeur du composant qui doit implémenter ces mécanismes tandis que
563 dans la couche DSC_User c'est au développeur des ports de se charger de ces fonctionnalités.
565 Les méthodes sont les suivantes :
571 virtual const char * get_repository_id() = 0;
573 virtual void uses_port_changed(Engines::DSC::uses_port * new_uses_port,
574 const Engines::DSC::Message message) = 0;
576 Pour le côté provides :
578 virtual Ports::Port_ptr get_port_ref() = 0;
580 virtual void provides_port_changed(int connection_nbr,
581 const Engines::DSC::Message message) {};
583 Du côté uses, il y a tout d'abord la méthode get_repository_id(). Elle permet d'obtenir
584 le typecode CORBA du port. Il s'agit de fournir la même information que le premier argument
585 de add_uses_port de la couche Basic. La méthode uses_port_changed(…) permet au port d'être
586 averti des nouvelle connexions avec des port provides et de gérer la liste des connexions.
588 Du côté provides, get_port_ref() permet d'obtenir une référence CORBA sur le servant. Enfin
589 la méthode provides_port_changed(…) peut être surdéfini si le port provides utilise
590 l'information provenant des connexions/déconnexions.
592 Dans l' exemple, le port provides est implémenté par la classe data_short_mes_ports_provides
593 et le port uses est implémenté par la classe data_short_mes_ports_uses.