1 // Copyright (C) 2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : CalciumCxxInterface.hxx
23 // Author : Eric Fayolle (EDF)
25 // Modified by : $LastChangedBy$
26 // Date : $LastChangedDate: 2007-03-01 13:27:58 +0100 (jeu, 01 mar 2007) $
29 #ifndef _CALCIUM_CXXINTERFACE_HXX_
30 #define _CALCIUM_CXXINTERFACE_HXX_
35 #include "Superv_Component_i.hxx"
36 #include "CalciumException.hxx"
37 #include "CalciumTypes.hxx"
38 #include "CalciumGenericUsesPort.hxx"
39 #include "Copy2UserSpace.hxx"
40 #include "Copy2CorbaSpace.hxx"
41 #include "CalciumPortTraits.hxx"
47 template <typename T1, typename T2>
49 static const bool value = false;
51 template <typename T1>
52 struct IsSameType<T1,T1> {
53 static const bool value = true;
58 namespace CalciumInterface {
60 /********************* INTERFACE DE DECONNEXION *****************/
63 ecp_fin (Superv_Component_i & component, bool provideLastGivenValue)
65 std::vector<std::string> usesPortNames;
66 std::vector<std::string>::const_iterator it;
67 component.get_uses_port_names(usesPortNames);
69 //récupérer le type de réel du port est un peu difficile
70 //car l'interface nous donne aucune indication
72 // uses_port *myUsesPort;
73 calcium_uses_port* myCalciumUsesPort;
75 for (it=usesPortNames.begin(); it != usesPortNames.end(); ++it) {
79 component.Superv_Component_i::get_port< calcium_uses_port >((*it).c_str());
81 // component.Superv_Component_i::get_port(myUsesPort,(*it).c_str());
82 // calcium_uses_port* myCalciumUsesPort=
83 // dynamic_cast<calcium_uses_port*>(myUsesPort);
86 std::cerr << "-------- CalciumInterface(ecp_fin) MARK 1 -|"<< *it <<"|----"<<
87 // typeid(myUsesPort).name() <<"-------------" <<
88 typeid(myCalciumUsesPort).name() <<"-------------" << std::endl;
91 // if ( !myCalciumUsesPort )
92 // throw Superv_Component_i::BadCast(LOC(OSS()<<"Impossible de convertir le port "
93 // << *it << " en port de type calcium_uses_port." ));
95 myCalciumUsesPort->disconnect(provideLastGivenValue);
97 } catch ( const Superv_Component_i::BadCast & ex) {
99 std::cerr << ex.what() << std::endl;
101 throw (CalciumException(CalciumTypes::CPTPVR,ex));
102 } catch ( const DSC_Exception & ex) {
104 std::cerr << ex.what() << std::endl;
106 // Exception venant de SupervComponent :
107 // PortNotDefined(CPNMVR), PortNotConnected(CPLIEN)
108 // ou du port uses : Dsc_Exception
109 // On continue à traiter la deconnexion des autres ports uses
111 throw (CalciumException(CalciumTypes::CPATAL,"Exception innatendue"));
112 // En fonction du mode de gestion des erreurs throw;
118 /********************* INTERFACES DE DESALLOCATION *****************/
120 // Uniquement appelé par l'utilisateur s'il utilise la 0 copie
121 // ( pointeur de données data==NULL à l'appel de ecp_lecture )
122 // Une désallocation aura lieu uniquement si un buffer intermédiaire
123 // était necessaire (type utilisateur et corba diffférent)
124 // La propriété du buffer est rendue à CORBA sinon
125 template <typename T1, typename T2> static void
126 ecp_free ( T1 * dataPtr )
128 typedef typename ProvidesPortTraits<T2>::PortType PortType;
129 typedef typename PortType::DataManipulator DataManipulator;
130 typedef typename DataManipulator::Type DataType; // Attention != T
131 typedef typename DataManipulator::InnerType InnerType;
133 DeleteTraits<IsSameType<T1,InnerType>::value >::apply(dataPtr);
136 template <typename T1> static void
137 ecp_free ( T1 * dataPtr )
139 ecp_free<T1,T1> ( dataPtr );
143 /********************* INTERFACES DE LECTURE *****************/
145 // T1 est le type de données
146 template <typename T1 > static void
147 ecp_lecture ( Superv_Component_i & component,
148 CalciumTypes::DependencyType dependencyType,
152 const string & nomVar,
157 ecp_lecture<T1,T1> (component,dependencyType,ti,tf,
158 i,nomVar,bufferLength,nRead,data);
162 // T1 est le type de données
163 // T2 est un <nom> de type Calcium permettant de sélectionner le port correspondant
164 // T1 et T2 sont dissociés pour discriminer le cas des nombres complexes
165 // -> Les données des nombres complexes sont de type float mais
166 // le port à utiliser est le port cplx
167 template <typename T1, typename T2 > static void
168 ecp_lecture ( Superv_Component_i & component,
169 CalciumTypes::DependencyType dependencyType,
173 const string & nomVar,
181 typedef typename ProvidesPortTraits<T2>::PortType PortType;
182 typedef typename PortType::DataManipulator DataManipulator;
183 typedef typename DataManipulator::Type CorbaDataType; // Attention != T1
184 typedef typename DataManipulator::InnerType InnerType;
186 CorbaDataType corbaData;
189 std::cerr << "-------- CalciumInterface(ecp_lecture) MARK 1 ------------------" << std::endl;
193 throw CalciumException(CalciumTypes::CPNMVR,
194 LOC("Le nom de la variable est <nul>"));
197 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 2 ------------------" << std::endl;
201 port = component.Superv_Component_i::get_port< PortType > (nomVar.c_str());
203 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 3 ------------------" << std::endl;
205 } catch ( const Superv_Component_i::PortNotDefined & ex) {
207 std::cerr << ex.what() << std::endl;
209 throw (CalciumException(CalciumTypes::CPNMVR,ex));
210 } catch ( const Superv_Component_i::PortNotConnected & ex) {
212 std::cerr << ex.what() << std::endl;;
214 throw (CalciumException(CalciumTypes::CPLIEN,ex));
215 // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
216 } catch ( const Superv_Component_i::BadCast & ex) {
218 std::cerr << ex.what() << std::endl;
220 throw (CalciumException(CalciumTypes::CPTPVR,ex));
223 // mode == mode du port
224 CalciumTypes::DependencyType portDependencyType = port->getDependencyType();
226 if ( portDependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
227 throw CalciumException(CalciumTypes::CPIT,
228 LOC(OSS()<<"Le mode de dépendance de la variable "
229 << nomVar << " est indéfini."));
231 if ( ( portDependencyType != dependencyType ) &&
232 ( dependencyType != CalciumTypes::SEQUENCE_DEPENDENCY ) )
233 throw CalciumException(CalciumTypes::CPITVR,
234 LOC(OSS()<<"Le mode de dépendance de la variable "
235 << nomVar << ": " << portDependencyType
236 << " ne correspond pas au mode demandé."));
239 if ( dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
240 corbaData = port->get(ti,tf, 0);
242 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 5 ------------------" << std::endl;
245 else if ( dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
246 corbaData = port->get(0, i);
248 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 6 ------------------" << std::endl;
251 // Lecture en séquence
253 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 7 ------------------" << std::endl;
255 corbaData = port->next(ti,i);
259 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 8 ------------------" << std::endl;
261 size_t corbaDataSize = DataManipulator::size(corbaData);
263 std::cout << "-------- CalciumInterface(ecp_lecture) corbaDataSize : " << corbaDataSize << std::endl;
266 // Vérifie si l'utilisateur demande du 0 copie
267 if ( data == NULL ) {
268 if ( bufferLength != 0 ) {
269 MESSAGE("bufferLength devrait valoir 0 pour l'utilisation du mode sans copie (data==NULL)");
271 nRead = corbaDataSize;
272 // Si les types T et InnerType sont différents, il faudra effectuer tout de même une recopie
273 if (!IsSameType<T1,InnerType>::value) data = new T1[nRead];
275 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 9 ------------------" << std::endl;
277 // On essaye de faire du 0 copy si les types T1 et InnerType sont les mêmes
278 Copy2UserSpace< IsSameType<T1,InnerType>::value >::apply(data,corbaData,nRead);
280 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 10 ------------------" << std::endl;
282 // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
283 // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
284 // DataManipulator::delete_data(corbaData);
285 // old : Dans les deux cas la structure CORBA n'est plus utile
286 // old : Si !IsSameType<T1,InnerType>::value l'objet CORBA est détruit avec son contenu
287 // old : Dans l'autre cas seul la coquille CORBA est détruite
288 // L'utilisateur devra appeler ecp_free (version modifiée) qui déterminera s'il est necessaire
289 // de désallouer un buffer intermédiaire ( types différents) ou de rendre la propriété
291 nRead = std::min < size_t > (corbaDataSize,bufferLength);
293 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 11 ------------------" << std::endl;
295 Copy2UserSpace<false>::apply(data,corbaData,nRead);
297 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 12 ------------------" << std::endl;
299 // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
300 // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
301 // DataManipulator::delete_data(corbaData);
304 std::cout << "-------- CalciumInterface(ecp_lecture), Valeur de data : " << std::endl;
305 std::copy(data,data+nRead,std::ostream_iterator<T1>(std::cout," "));
306 std::cout << "Ptr :" << data << std::endl;
308 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 13 ------------------" << std::endl;
316 /********************* INTERFACES D'ECRITURE *****************/
318 template <typename T1> static void
319 ecp_ecriture ( Superv_Component_i & component,
320 CalciumTypes::DependencyType dependencyType,
323 const string & nomVar,
326 ecp_ecriture<T1,T1> (component,dependencyType,t,i,nomVar,bufferLength,data);
329 template <typename T1, typename T2> static void
330 ecp_ecriture ( Superv_Component_i & component,
331 CalciumTypes::DependencyType dependencyType,
334 const string & nomVar,
341 //typedef typename StarTrait<TT>::NonStarType T;
342 typedef typename UsesPortTraits<T2>::PortType PortType;
343 typedef typename ProvidesPortTraits<T2>::PortType ProvidesPortType;
344 typedef typename ProvidesPortType::DataManipulator DataManipulator;
345 // Verifier que l'on peut définir UsesPortType::DataManipulator
346 // typedef typename PortType::DataManipulator DataManipulator;
347 typedef typename DataManipulator::Type CorbaDataType; // Attention != T1
348 typedef typename DataManipulator::InnerType InnerType;
351 std::cerr << "-------- CalciumInterface(ecriture) MARK 1 ------------------" << std::endl;
353 if ( nomVar.empty() ) throw CalciumException(CalciumTypes::CPNMVR,
354 LOC("Le nom de la variable est <nul>"));
357 std::cout << "-------- CalciumInterface(ecriture) MARK 2 ------------------" << std::endl;
361 port = component.Superv_Component_i::get_port< PortType > (nomVar.c_str());
363 std::cout << "-------- CalciumInterface(ecriture) MARK 3 ------------------" << std::endl;
365 } catch ( const Superv_Component_i::PortNotDefined & ex) {
367 std::cerr << ex.what() << std::endl;
369 throw (CalciumException(CalciumTypes::CPNMVR,ex));
370 } catch ( const Superv_Component_i::PortNotConnected & ex) {
372 std::cerr << ex.what() << std::endl;;
374 throw (CalciumException(CalciumTypes::CPLIEN,ex));
375 // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
376 } catch ( const Superv_Component_i::BadCast & ex) {
378 std::cerr << ex.what() << std::endl;
380 throw (CalciumException(CalciumTypes::CPTPVR,ex));
383 // mode == mode du port
384 // On pourrait créer la méthode CORBA dans le mode de Couplage CALCIUM.
385 // et donc ajouter cette cette méthode uniquement dans l'IDL calcium !
387 // CalciumTypes::DependencyType portDependencyType;
389 // portDependencyType = port->getDependencyType();
390 // std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
391 // } catch ( const DSC_Exception & ex ) {
392 // std::cerr << ex.what() << std::endl;;
393 // throw (CalciumException(CalciumTypes::CPIT,ex));
396 if ( dependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
397 throw CalciumException(CalciumTypes::CPIT,
398 LOC(OSS()<<"Le mode de dépendance demandé pour la variable "
399 << nomVar << " est indéfini."));
401 if ( dependencyType == CalciumTypes::SEQUENCE_DEPENDENCY )
402 throw CalciumException(CalciumTypes::CPIT,
403 LOC(OSS()<<"Le mode de dépendance SEQUENCE_DEPENDENCY pour la variable "
404 << nomVar << " est impossible en écriture."));
406 // Il faudrait que le port provides génère une exception si le mode donnée n'est pas
407 // le bon. La seule façon de le faire est d'envoyer -1 en temps si on n'est en itération
408 // et vice-versa pour informer les provides port du mode dans lequel on est. Sinon il faut
409 // modifier l'interface IDL pour y ajouter un mode de dépendance !
411 // if ( portDependencyType != dependencyType )
412 // throw CalciumException(CalciumTypes::CPITVR,
413 // LOC(OSS()<<"Le mode de dépendance de la variable "
414 // << nomVar << " ne correspond pas au mode demandé."));
417 if ( bufferLength < 1 )
418 throw CalciumException(CalciumTypes::CPNTNULL,
419 LOC(OSS()<<"Le buffer a envoyer est de taille nulle "));
423 std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
425 CorbaDataType corbaData;
428 // Si les types Utilisateurs et CORBA sont différents
429 // il faut effectuer une recopie sinon on utilise directement le
430 // buffer data pour constituer la séquence
432 // - Attention en mode asynchrone il faudra eventuellement
433 // faire une copie des données même si elles sont de même type.
434 // - OLD : En cas de collocalisation (du port provide et du port uses)
435 // OLD : il est necessaire d'effectuer une recopie du buffer car la
436 // OLD : séquence est envoyée au port provide par une référence sur
437 // OLD : la séquence locale. Or la méthode put récupère le buffer directement
438 // OLD : qui est alors le buffer utilisateur. Il pourrait alors arriver que :
439 // OLD : * Le recepteur efface le buffer emetteur
440 // OLD : * Le port lui-même efface le buffer de l'ulisateur !
441 // OLD : Cette copie est effectuée dans GenericPortUses::put
442 // OLD : en fonction de la collocalisation ou non.
443 // - OLD :En cas de connection multiples d'un port uses distant vers plusieurs port provides
444 // OLD : collocalisés les ports provides partagent la même copie de la donnée !
445 // OLD : Il faut effectuer une copie dans le port provides.
446 // OLD : Cette copie est effectuée dans GenericPortUses::put
447 // OLD : en fonction de la collocalisation ou non.
448 Copy2CorbaSpace<IsSameType<T1,InnerType>::value >::apply(corbaData,data,bufferLength);
450 //TODO : GERER LES EXCEPTIONS ICI : ex le port n'est pas connecté
451 if ( dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
454 port->put(*corbaData,t, -1);
456 catch ( const DSC_Exception & ex)
458 throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
460 //Le -1 peut être traité par le cst DataIdContainer et transformé en 0
461 //Etre obligé de mettre une étoile ds (*corbadata) va poser des pb pour les types <> seq
463 std::cout << "-------- CalciumInterface(ecriture) MARK 5 ------------------" << std::endl;
466 else if ( dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
469 port->put(*corbaData,-1, i);
471 catch ( const DSC_Exception & ex)
473 throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
476 std::cout << "-------- CalciumInterface(ecriture) MARK 6 ------------------" << std::endl;
482 std::cout << "-------- CalciumInterface(ecriture), Valeur de corbaData : " << std::endl;
483 for (int i = 0; i < corbaData->length(); ++i)
484 cout << "-------- CalciumInterface(ecriture), corbaData[" << i << "] = " << (*corbaData)[i] << endl;
487 // if ( !IsSameType<T1,InnerType>::value ) delete corbaData;
488 // Supprime l'objet CORBA avec eventuellement les données qu'il contient (cas de la recopie)
492 std::cout << "-------- CalciumInterface(ecriture) MARK 7 ------------------" << std::endl;