1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // 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;
57 #include <boost/type_traits/remove_all_extents.hpp>
59 namespace CalciumInterface {
61 /********************* INTERFACE DE DECONNEXION *****************/
64 ecp_cd (Superv_Component_i & component, std::string & instanceName)
66 /* TODO : Trouver le nom de l'instance SALOME*/
67 if (instanceName.empty()) instanceName="UNDEFINED";
72 ecp_fin (Superv_Component_i & component, bool provideLastGivenValue)
74 std::vector<std::string> usesPortNames;
75 std::vector<std::string>::const_iterator it;
76 component.get_uses_port_names(usesPortNames);
78 //Récupérer le type de réel du port est un peu difficile
79 //car l'interface ne donne aucune indication
81 // uses_port *myUsesPort;
82 calcium_uses_port* myCalciumUsesPort;
84 for (it=usesPortNames.begin(); it != usesPortNames.end(); ++it) {
88 component.Superv_Component_i::get_port< calcium_uses_port >((*it).c_str());
90 // component.Superv_Component_i::get_port(myUsesPort,(*it).c_str());
91 // calcium_uses_port* myCalciumUsesPort=
92 // dynamic_cast<calcium_uses_port*>(myUsesPort);
95 std::cerr << "-------- CalciumInterface(ecp_fin) MARK 1 -|"<< *it <<"|----"<<
96 // typeid(myUsesPort).name() <<"-------------" <<
97 typeid(myCalciumUsesPort).name() <<"-------------" << std::endl;
100 // if ( !myCalciumUsesPort )
101 // throw Superv_Component_i::BadCast(LOC(OSS()<<"Impossible de convertir le port "
102 // << *it << " en port de type calcium_uses_port." ));
104 myCalciumUsesPort->disconnect(provideLastGivenValue);
106 } catch ( const Superv_Component_i::BadCast & ex) {
108 std::cerr << ex.what() << std::endl;
110 throw (CalciumException(CalciumTypes::CPTPVR,ex));
111 } catch ( const DSC_Exception & ex) {
113 std::cerr << ex.what() << std::endl;
115 // Exception venant de SupervComponent :
116 // PortNotDefined(CPNMVR), PortNotConnected(CPLIEN)
117 // ou du port uses : Dsc_Exception
118 // On continue à traiter la deconnexion des autres ports uses
120 throw (CalciumException(CalciumTypes::CPATAL,"Exception innatendue"));
121 // En fonction du mode de gestion des erreurs throw;
127 /********************* INTERFACES DE DESALLOCATION *****************/
129 // Uniquement appelé par l'utilisateur s'il utilise la 0 copie
130 // ( pointeur de données data==NULL à l'appel de ecp_lecture )
131 // Une désallocation aura lieu uniquement si un buffer intermédiaire
132 // était necessaire (type utilisateur et corba diffférent)
133 // La propriété du buffer est rendue à CORBA sinon
134 template <typename T1, typename T2> static void
135 ecp_free ( T1 * dataPtr )
137 typedef typename ProvidesPortTraits<T2>::PortType PortType;
138 typedef typename PortType::DataManipulator DataManipulator;
139 typedef typename DataManipulator::Type DataType; // Attention != T1
140 typedef typename DataManipulator::InnerType InnerType;
142 DeleteTraits<IsSameType<T1,InnerType>::value, DataManipulator >::apply(dataPtr);
145 template <typename T1> static void
146 ecp_free ( T1 * dataPtr )
148 ecp_free<T1,T1> ( dataPtr );
152 /********************* INTERFACES DE LECTURE *****************/
155 // T1 est le type de données
156 // T2 est un <nom> de type Calcium permettant de sélectionner le port CORBA correspondant
157 // T1 et T2 sont dissociés pour discriminer le cas des nombres complexes
158 // -> Les données des nombres complexes sont de type float mais
159 // le port à utiliser est le port cplx
160 template <typename T1, typename T2 > static void
161 ecp_lecture ( Superv_Component_i & component,
162 int const & dependencyType,
166 const std::string & nomVar,
174 typedef typename ProvidesPortTraits<T2>::PortType PortType;
175 typedef typename PortType::DataManipulator DataManipulator;
176 typedef typename DataManipulator::Type CorbaDataType; // Attention != T1
177 typedef typename DataManipulator::InnerType InnerType;
178 CalciumTypes::DependencyType _dependencyType=
179 static_cast<CalciumTypes::DependencyType>(dependencyType);
181 CorbaDataType corbaData;
184 std::cerr << "-------- CalciumInterface(ecp_lecture) MARK 1 ------------------" << std::endl;
188 throw CalciumException(CalciumTypes::CPNMVR,
189 LOC("Le nom de la variable est <nul>"));
192 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 2 ------------------" << std::endl;
196 port = component.Superv_Component_i::get_port< PortType > (nomVar.c_str());
198 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 3 ------------------" << std::endl;
200 } catch ( const Superv_Component_i::PortNotDefined & ex) {
202 std::cerr << ex.what() << std::endl;
204 throw (CalciumException(CalciumTypes::CPNMVR,ex));
205 } catch ( const Superv_Component_i::PortNotConnected & ex) {
207 std::cerr << ex.what() << std::endl;;
209 throw (CalciumException(CalciumTypes::CPLIEN,ex));
210 // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
211 } catch ( const Superv_Component_i::BadCast & ex) {
213 std::cerr << ex.what() << std::endl;
215 throw (CalciumException(CalciumTypes::CPTPVR,ex));
218 // mode == mode du port
219 CalciumTypes::DependencyType portDependencyType = port->getDependencyType();
221 if ( portDependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
222 throw CalciumException(CalciumTypes::CPIT,
223 LOC(OSS()<<"Le mode de dépendance de la variable "
224 << nomVar << " est indéfini."));
226 if ( ( portDependencyType != _dependencyType ) &&
227 ( _dependencyType != CalciumTypes::SEQUENCE_DEPENDENCY ) )
228 throw CalciumException(CalciumTypes::CPITVR,
229 LOC(OSS()<<"Le mode de dépendance de la variable "
230 << nomVar << ": " << portDependencyType
231 << " ne correspond pas au mode demandé."));
234 if ( _dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
235 corbaData = port->get(ti,tf, 0);
237 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 5 ------------------" << std::endl;
240 else if ( _dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
241 corbaData = port->get(0, i);
243 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 6 ------------------" << std::endl;
246 // Lecture en séquence
248 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 7 ------------------" << std::endl;
250 corbaData = port->next(ti,i);
254 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 8 ------------------" << std::endl;
256 size_t corbaDataSize = DataManipulator::size(corbaData);
258 std::cout << "-------- CalciumInterface(ecp_lecture) corbaDataSize : " << corbaDataSize << std::endl;
261 // Vérifie si l'utilisateur demande du 0 copie
262 if ( data == NULL ) {
263 if ( bufferLength != 0 ) {
264 MESSAGE("bufferLength devrait valoir 0 pour l'utilisation du mode sans copie (data==NULL)");
266 nRead = corbaDataSize;
267 // Si les types T1 et InnerType sont différents, il faudra effectuer tout de même une recopie
268 if (!IsSameType<T1,InnerType>::value) data = new T1[nRead];
270 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 9 ------------------" << std::endl;
272 // On essaye de faire du 0 copy si les types T1 et InnerType sont les mêmes.
274 // La raison d'être du foncteur Copy2UserSpace est que le compilateur n'acceptera
275 // pas une expresion d'affectation sur des types incompatibles même
276 // si cette expression se trouve dans une branche non exécuté d'un test
277 // sur la compatibilité des types.
278 // En utilisant le foncteur Copy2UserSpace, seul la spécialisation en adéquation
279 // avec la compatibilité des types sera compilée
280 Copy2UserSpace< IsSameType<T1,InnerType>::value, DataManipulator >::apply(data,corbaData,nRead);
282 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 10 ------------------" << std::endl;
284 // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
285 // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
286 // DataManipulator::delete_data(corbaData);
287 // ni DataManipulator::getPointer(corbaData,true); qui détruit la sequence lorsque l'on
288 // prend la propriété du buffer
289 // old : Dans les deux cas la structure CORBA n'est plus utile
290 // old : Si !IsSameType<T1,InnerType>::value l'objet CORBA est détruit avec son contenu
291 // old : Dans l'autre cas seul la coquille CORBA est détruite
292 // L'utilisateur devra appeler ecp_free qui déterminera s'il est necessaire
293 // de désallouer un buffer intermédiaire ( types différents) ou de rendre la propriété
295 nRead = std::min < size_t > (corbaDataSize,bufferLength);
297 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 11 ------------------" << std::endl;
299 Copy2UserSpace<false, DataManipulator >::apply(data,corbaData,nRead);
300 DataManipulator::copy(corbaData,data,nRead);
303 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 12 ------------------" << std::endl;
305 // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
306 // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
307 // DataManipulator::delete_data(corbaData);
310 std::cout << "-------- CalciumInterface(ecp_lecture), Valeur de data : " << std::endl;
311 std::copy(data,data+nRead,std::ostream_iterator<T1>(std::cout," "));
312 std::cout << "Ptr :" << data << std::endl;
314 std::cout << "-------- CalciumInterface(ecp_lecture) MARK 13 ------------------" << std::endl;
321 // T1 est le type de données
322 template <typename T1 > static void
323 ecp_lecture ( Superv_Component_i & component,
324 int const & dependencyType,
328 const std::string & nomVar,
333 ecp_lecture<T1,T1> (component,dependencyType,ti,tf,
334 i,nomVar,bufferLength,nRead,data);
338 /********************* INTERFACES D'ECRITURE *****************/
342 template <typename T1, typename T2> static void
343 ecp_ecriture ( Superv_Component_i & component,
344 int const & dependencyType,
347 const std::string & nomVar,
354 //typedef typename StarTrait<TT>::NonStarType T;
355 typedef typename boost::remove_all_extents< T2 >::type T2_without_extent;
356 typedef typename boost::remove_all_extents< T1 >::type T1_without_extent;
358 typedef typename UsesPortTraits <T2_without_extent>::PortType UsesPortType;
359 typedef typename ProvidesPortTraits<T2_without_extent>::PortType ProvidesPortType;// pour obtenir un manipulateur de données
360 typedef typename ProvidesPortType::DataManipulator DataManipulator;
361 // Verifier que l'on peut définir UsesPortType::DataManipulator
362 // typedef typename PortType::DataManipulator DataManipulator;
363 typedef typename DataManipulator::Type CorbaDataType; // Attention != T1
364 typedef typename DataManipulator::InnerType InnerType;
366 T1_without_extent const & _data = data;
368 CalciumTypes::DependencyType _dependencyType=
369 static_cast<CalciumTypes::DependencyType>(dependencyType);
372 std::cerr << "-------- CalciumInterface(ecriture) MARK 1 ------------------" << std::endl;
374 if ( nomVar.empty() ) throw CalciumException(CalciumTypes::CPNMVR,
375 LOC("Le nom de la variable est <nul>"));
378 std::cout << "-------- CalciumInterface(ecriture) MARK 2 ------------------" << std::endl;
382 port = component.Superv_Component_i::get_port< UsesPortType > (nomVar.c_str());
384 std::cout << "-------- CalciumInterface(ecriture) MARK 3 ------------------" << std::endl;
386 } catch ( const Superv_Component_i::PortNotDefined & ex) {
388 std::cerr << ex.what() << std::endl;
390 throw (CalciumException(CalciumTypes::CPNMVR,ex));
391 } catch ( const Superv_Component_i::PortNotConnected & ex) {
393 std::cerr << ex.what() << std::endl;;
395 throw (CalciumException(CalciumTypes::CPLIEN,ex));
396 // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
397 } catch ( const Superv_Component_i::BadCast & ex) {
399 std::cerr << ex.what() << std::endl;
401 throw (CalciumException(CalciumTypes::CPTPVR,ex));
404 // mode == mode du port
405 // On pourrait créer la méthode CORBA dans le mode de Couplage CALCIUM.
406 // et donc ajouter cette cette méthode uniquement dans l'IDL calcium !
408 // CalciumTypes::DependencyType portDependencyType;
410 // portDependencyType = port->getDependencyType();
411 // std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
412 // } catch ( const DSC_Exception & ex ) {
413 // std::cerr << ex.what() << std::endl;;
414 // throw (CalciumException(CalciumTypes::CPIT,ex));
417 if ( _dependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
418 throw CalciumException(CalciumTypes::CPIT,
419 LOC(OSS()<<"Le mode de dépendance demandé pour la variable "
420 << nomVar << " est indéfini."));
422 if ( _dependencyType == CalciumTypes::SEQUENCE_DEPENDENCY )
423 throw CalciumException(CalciumTypes::CPIT,
424 LOC(OSS()<<"Le mode de dépendance SEQUENCE_DEPENDENCY pour la variable "
425 << nomVar << " est impossible en écriture."));
427 // Il faudrait que le port provides génère une exception si le mode donnée n'est pas
428 // le bon. La seule façon de le faire est d'envoyer -1 en temps si on n'est en itération
429 // et vice-versa pour informer les provides port du mode dans lequel on est. Sinon il faut
430 // modifier l'interface IDL pour y ajouter un mode de dépendance !
432 // if ( portDependencyType != _dependencyType )
433 // throw CalciumException(CalciumTypes::CPITVR,
434 // LOC(OSS()<<"Le mode de dépendance de la variable "
435 // << nomVar << " ne correspond pas au mode demandé."));
438 if ( bufferLength < 1 )
439 throw CalciumException(CalciumTypes::CPNTNULL,
440 LOC(OSS()<<"Le buffer a envoyer est de taille nulle "));
444 std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
446 CorbaDataType corbaData;
449 // Si les types Utilisateurs et CORBA sont différents
450 // il faut effectuer une recopie sinon on utilise directement le
451 // buffer data pour constituer la séquence
453 // - Attention en mode asynchrone il faudra eventuellement
454 // faire une copie des données même si elles sont de même type.
455 // - OLD : En cas de collocalisation (du port provide et du port uses)
456 // OLD : il est necessaire d'effectuer une recopie du buffer car la
457 // OLD : séquence est envoyée au port provide par une référence sur
458 // OLD : la séquence locale. Or la méthode put récupère le buffer directement
459 // OLD : qui est alors le buffer utilisateur. Il pourrait alors arriver que :
460 // OLD : * Le recepteur efface le buffer emetteur
461 // OLD : * Le port lui-même efface le buffer de l'utilisateur !
462 // OLD : Cette copie est effectuée dans GenericPortUses::put
463 // OLD : en fonction de la collocalisation ou non.
464 // - OLD :En cas de connection multiples d'un port uses distant vers plusieurs port provides
465 // OLD : collocalisés les ports provides partagent la même copie de la donnée !
466 // OLD : Il faut effectuer une copie dans le port provides.
467 // OLD : Cette copie est effectuée dans GenericPortUses::put
468 // OLD : en fonction de la collocalisation ou non.
469 Copy2CorbaSpace<IsSameType<T1_without_extent,InnerType>::value, DataManipulator >::apply(corbaData,_data,bufferLength);
471 //TODO : GERER LES EXCEPTIONS ICI : ex le port n'est pas connecté
472 if ( _dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
475 port->put(*corbaData,t, -1);
477 catch ( const DSC_Exception & ex)
479 throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
481 //Le -1 peut être traité par le cst DataIdContainer et transformé en 0
482 //Etre obligé de mettre une étoile ds (*corbadata) va poser des pb pour les types <> seq
484 std::cout << "-------- CalciumInterface(ecriture) MARK 5 ------------------" << std::endl;
487 else if ( _dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
490 port->put(*corbaData,-1, i);
492 catch ( const DSC_Exception & ex)
494 throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
497 std::cout << "-------- CalciumInterface(ecriture) MARK 6 ------------------" << std::endl;
503 std::cout << "-------- CalciumInterface(ecriture), Valeur de corbaData : " << std::endl;
504 for (int i = 0; i < corbaData->length(); ++i)
505 std::cout << "-------- CalciumInterface(ecriture), corbaData[" << i << "] = " << (*corbaData)[i] << std::endl;
508 // if ( !IsSameType<T1,InnerType>::value ) delete corbaData;
509 // Supprime l'objet CORBA avec eventuellement les données qu'il contient (cas de la recopie)
513 std::cout << "-------- CalciumInterface(ecriture) MARK 7 ------------------" << std::endl;
519 template <typename T1> static void
520 ecp_ecriture ( Superv_Component_i & component,
521 int const & dependencyType,
524 const std::string & nomVar,
527 ecp_ecriture<T1,T1> (component,dependencyType,t,i,nomVar,bufferLength,data);