Version: 9.12.0
GenericPort.hxx
Go to the documentation of this file.
1 // Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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, or (at your option) any later version.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 
23 // File : GenericPort.hxx
24 // Author : Eric Fayolle (EDF)
25 // Module : KERNEL
26 // Modified by : $LastChangedBy$
27 // Date : $LastChangedDate: 2007-02-28 15:26:32 +0100 (mer, 28 fév 2007) $
28 // Id : $Id$
29 //
30 #ifndef _GENERIC_PORT_HXX_
31 #define _GENERIC_PORT_HXX_
32 
33 #include "CorbaTypeManipulator.hxx"
34 
35 #include "Superv_Component_i.hxx"
36 // SALOME CORBA Exception
37 #include "Utils_CorbaException.hxx"
38 // SALOME C++ Exception
40 #include "DSC_Exception.hxx"
41 #include "utilities.h"
42 #include "DisplayPair.hxx"
43 
44 #include <iostream>
45 #include <map>
46 
47 // Inclusions pour l'affichage
48 #include <algorithm>
49 #include <iterator>
50 
51 // Classe GenericPort
52 // --------------------------------
53 //
54 // Definition: Implemente un port de type "data-stream"
55 // Cette implémentation gère tous les types de données définies par DataManipulator::type
56 // Ce port est soumis à une politique d'itération sur les identificateurs de données (DataId)
57 // Un identificateur de données est construit à partir d'un ou plusieurs paramètres de la méthode put
58 // tels que : une date, une itération, un pas de temps ou une combinaison de ces paramètres.
59 
60 template < typename DataManipulator, class COUPLING_POLICY >
61 class GenericPort : public COUPLING_POLICY {
62 public:
63  // Type de données manipulés
64  typedef typename DataManipulator::Type DataType;
65  typedef typename DataManipulator::CorbaInType CorbaInDataType;
66 
68  virtual ~GenericPort();
69 
70  template <typename TimeType,typename TagType> void put(CorbaInDataType data, TimeType time, TagType tag);
71  template <typename TimeType,typename TagType> DataType get(TimeType time, TagType tag);
72  template <typename TimeType,typename TagType> DataType get(TimeType& ti, TimeType tf, TagType tag = 0);
73  template <typename TimeType,typename TagType> DataType next(TimeType &t, TagType &tag );
74  void close (PortableServer::POA_var poa, PortableServer::ObjectId_var id);
75  void wakeupWaiting();
76  template <typename TimeType,typename TagType> void erase(TimeType time, TagType tag, bool before );
77 
78 private:
79 
80  // Type identifiant une instance de donnee. Exemple (time,tag)
81  typedef typename COUPLING_POLICY::DataId DataId;
82  typedef std::map< DataId, DataType> DataTable;
83 
84  // Stockage des donnees recues et non encore distribuées
86 
87  // Indicateur que le destinataire attend une instance particuliere de données
89  // Indicateur que le destinataire attend n'importe qu'elle instance de données
91 
92  // Identificateur de la donné que le destinataire (propriétaire du port) attend
94  // Sauvegarde du DataId courant pour la méthode next
97  // Exclusion mutuelle d'acces a la table des données reçues
98  omni_mutex storedDatas_mutex;
99  // Condition d'attente d'une instance (Le processus du Get attend la condition declaree par le processus Put)
100  omni_condition cond_instance;
101 
102 };
103 
104 template < typename DataManipulator, typename COUPLING_POLICY >
106  waitingForConvenientDataId(false),waitingForAnyDataId(false),lastDataIdSet(false),
107  cond_instance(& this->storedDatas_mutex){}
108 
109 template < typename DataManipulator, typename COUPLING_POLICY>
111  typename DataTable::iterator it;
112  for (it=storedDatas.begin(); it!=storedDatas.end(); ++it) {
114  std::cerr << "~GenericPort() : destruction de la donnnée associée au DataId :" << (*it).first << std::endl;
115 
116  DataManipulator::delete_data( (*it).second );
117  }
118 }
119 
120 template < typename DataManipulator, typename COUPLING_POLICY> void
122  PortableServer::ObjectId_var id) {
123  // Ferme le port en supprimant le servant
124  // La desactivation du servant du POA provoque sa suppression
125  poa->deactivate_object (id);
126 }
127 
128 template < typename DataManipulator, typename COUPLING_POLICY> void
130 {
132  std::cout << "-------- wakeupWaiting ------------------" << std::endl;
133 
134  storedDatas_mutex.lock();
135  if (waitingForAnyDataId || waitingForConvenientDataId) {
137  {
138  std::cout << "-------- wakeupWaiting:signal --------" << std::endl;
139  std::cout << std::flush;
140  }
141 
142  cond_instance.signal();
143  }
144 
145  storedDatas_mutex.unlock();
146 }
147 
148 /* Methode put_generique
149  *
150  * Stocke en memoire une instance de donnee (pointeur) que l'emetteur donne a l'intention du destinataire.
151  * Reveille le destinataire, si il y a lieu.
152  */
153 template < typename DataManipulator, typename COUPLING_POLICY>
154 template < typename TimeType,typename TagType>
156  TimeType time,
157  TagType tag) {
158  fflush(stdout);
159  fflush(stderr);
160  try {
162  {
163  // Affichage des donnees pour DEBUGging
164  std::cerr << "parametres emis: " << time << ", " << tag << std::endl;
165  DataManipulator::dump(dataParam);
166  }
167 
168  // L'intérêt des paramètres time et tag pour ce port est décidé dans la politique de couplage
169  // Il est possible de filtrer en prenant en compte uniquement un paramètre time/tag ou les deux
170  // Il est également possible de convertir les données recues ou bien de les dupliquer
171  // pour plusieurs valeurs de time et/ou tag (d'où la notion de container dans la politique de couplage)
172  typedef typename COUPLING_POLICY::DataIdContainer DataIdContainer;
173  typedef typename COUPLING_POLICY::DataId DataId;
174 
175  DataId dataId(time,tag);
176  // Effectue les traitements spécifiques à la politique de couplage
177  // pour construire une liste d'ids (par filtrage, conversion ...)
178  // DataIdContainer dataIds(dataId,*(static_cast<const COUPLING_POLICY *>(this)));
179  DataIdContainer dataIds(dataId, *this);
180 
181  typename DataIdContainer::iterator dataIdIt = dataIds.begin();
182 
183  bool expectedDataReceived = false;
184 
186  std::cout << "-------- Put : MARK 1 ------------------" << std::endl;
187 
188  if ( dataIds.empty() ) return;
190  std::cout << "-------- Put : MARK 1bis ------------------" << std::endl;
191 
192  // Recupere les donnees venant de l'ORB et relâche les structures CORBA
193  // qui n'auraient plus cours en sortie de méthode put
194  DataType data = DataManipulator::get_data(dataParam);
195 
196  int nbOfIter = 0;
197 
199  {
200  std::cout << "-------- Put : MARK 2 ------ "<< (dataIdIt == dataIds.end()) << "------------" << std::endl;
201  std::cout << "-------- Put : MARK 2bis "<< (*dataIdIt) <<"------------------" << std::endl;
202  }
203  storedDatas_mutex.lock();
204 
205  for (;dataIdIt != dataIds.end();++dataIdIt) {
207  std::cout << "-------- Put : MARK 3 ------------------" << std::endl;
208 
209  // Duplique l'instance de donnée pour les autres dataIds
210  if (nbOfIter > 0) data = DataManipulator::clone(data);
212  std::cout << "-------- Put : MARK 3bis -----"<< dataIdIt.operator*() <<"------------" << std::endl;
213 
214  DataId currentDataId=*dataIdIt;
215 
217  {
218  std::cerr << "processing dataId : "<< currentDataId << std::endl;
219  std::cout << "-------- Put : MARK 4 ------------------" << std::endl;
220  }
221 
222  // Ajoute l'instance de la donnee a sa place dans la table de données
223  // ou remplace une instance précédente si elle existe
224 
225  // Recherche la première clé telle quelle ne soit pas < currentDataId
226  // pour celà l'opérateur de comparaison storedDatas.key_comp() est utilisé // <=> premier emplacement où l'on pourrait insérer notre DataId // <=> en général équivaux à (*wDataIt).first >= currentDataId typename DataTable::iterator wDataIt = storedDatas.lower_bound(currentDataId); if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 5 ------------------" << std::endl; // On n'a pas trouvé de dataId supérieur au notre ou // on a trouvé une clé > à cet Id if (wDataIt == storedDatas.end() || storedDatas.key_comp()(currentDataId,(*wDataIt).first) ) { if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 6 ------------------" << std::endl; // Ajoute la donnee dans la table wDataIt = storedDatas.insert(wDataIt, make_pair (currentDataId, data)); } else { // Si on n'est pas en fin de liste et qu'il n'y a pas de relation d'ordre strict // entre notre dataId et le DataId pointé c'est qu'ils sont identiques if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 7 ------------------" << std::endl; // Les données sont remplacées par les nouvelles valeurs // lorsque que le dataId existe déjà DataType old_data = (*wDataIt).second; (*wDataIt).second = data; // Detruit la vieille donnee DataManipulator::delete_data (old_data); } if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 8 ------------------" << std::endl; // Compte le nombre de dataIds à traiter ++nbOfIter; if (SALOME::VerbosityActivated()) { std::cout << "-------- Put : waitingForConvenientDataId : " << waitingForConvenientDataId << "---" << std::endl; std::cout << "-------- Put : waitingForAnyDataId : " << waitingForAnyDataId << "---" << std::endl; std::cout << "-------- Put : currentDataId : " << currentDataId << "---" << std::endl; std::cout << "-------- Put : expectedDataId : " << expectedDataId << "---" << std::endl; std::cout << "-------- Put : MARK 9 ------------------" << std::endl; } // A simplifier mais : // - pas possible de mettre des arguments optionnels à cause // du type itérator qui n'est pas connu (pas de possibilité de déclarer un static ) // - compliquer de créer une méthode sans les paramètres inutiles tout en réutilisant // la méthode initiale car cette dernière ne peut pas être déclarée virtuelle // à cause de ses paramètres templates. Du coup, il faudrait aussi redéfinir la // méthode simplifiée dans les classes définissant une politique // de couplage particulière ... bool dummy1,dummy2; typename DataTable::iterator dummy3; // Par construction, les valeurs de waitingForAnyDataId, waitingForConvenientDataId et de // expectedDataId ne peuvent pas être modifiées pendant le traitement de la boucle // sur les dataIds (à cause du lock utilisé dans la méthode put et les méthodes get ) // rem : Utilisation de l'évaluation gauche droite du logical C or if ( waitingForAnyDataId || ( waitingForConvenientDataId && this->isDataIdConveniant(storedDatas, expectedDataId, dummy1, dummy2, dummy3) ) ) { if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 10 ------------------" << std::endl; //Doit pouvoir réveiller le get ici (a vérifier) expectedDataReceived = true; } } if (expectedDataReceived) { if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 11 ------------------" << std::endl; // si waitingForAnyDataId était positionné, c'est forcément lui qui a activer // expectedDataReceived à true if (waitingForAnyDataId) waitingForAnyDataId = false; else waitingForConvenientDataId = false; // Reveille le thread du destinataire (stoppe son attente) // Ne faudrait-il pas réveiller plutôt tous les threads ? // Celui réveillé ne correspond pas forcément à celui qui demande // cet expectedDataReceived. // Pb1 : cas d'un un get séquentiel et d'un get sur un dataId que l'on vient de recevoir. // Si l'on reveille le mauvais thread, l'autre va attendre indéfiniment ! (sauf timeout) // Pb2 : également si deux attentes de DataIds même différents car on n'en stocke qu'un ! // Conclusion : Pour l'instant on ne gère pas un service multithreadé qui effectue // des lectures simultanées sur le même port ! if (SALOME::VerbosityActivated()) std::cerr << "-------- Put : new datas available ------------------" << std::endl; fflush(stdout);fflush(stderr); cond_instance.signal(); } if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 12 ------------------" << std::endl; // Deverouille l'acces a la table : On peut remonter l'appel au dessus de expected... storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 13 ------------------" << std::endl; fflush(stdout); fflush(stderr); } // Catch les exceptions SALOME//C++ pour la transformer en une exception SALOME//CORBA catch ( const SALOME_Exception & ex ) { // On évite de laisser un mutex storedDatas_mutex.unlock(); THROW_SALOME_CORBA_EXCEPTION(ex.what(), SALOME::INTERNAL_ERROR); } } // erase data before time or tag template < typename DataManipulator, typename COUPLING_POLICY > template <typename TimeType,typename TagType> void GenericPort<DataManipulator, COUPLING_POLICY>::erase(TimeType time, TagType tag, bool before) { typename COUPLING_POLICY::template EraseDataIdBeforeOrAfterTagProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas,time,tag,before); } // Version du Get en 0 copy // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas ) // ( L'utilisateur devra être attentif à la politique de gestion de l'historique // spécifique au mode de couplage car il peut y avoir une suppression potentielle // d'une donnée utilisée directement dans le code utilisateur ) // Le code doit prendre connaissance du transfert de propriété ou non des données // auprès du mode de couplage choisi. template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType time, TagType tag) // REM : Laisse passer toutes les exceptions // En particulier les SALOME_Exceptions qui viennent de la COUPLING_POLICY // Pour déclarer le throw avec l'exception spécifique il faut que je vérifie // qu'un setunexpeted est positionné sinon le C++ arrête tout par appel à terminate { typedef typename COUPLING_POLICY::DataId DataId; // (Pointeur sur séquence) ou valeur.. DataType dataToTransmit ; bool isEqual, isBounded; typedef typename DataManipulator::InnerType InnerType; if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 1 ------------------" << std::endl; expectedDataId = DataId(time,tag); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 2 ------------------" << std::endl; typename DataTable::iterator wDataIt1; try { storedDatas_mutex.lock(); // Gérer les Exceptions ds le corps de la méthode while ( true ) { // Renvoie isEqual si le dataId attendu est trouvé dans storedDatas : // - l'itérateur wDataIt1 pointe alors sur ce dataId // Renvoie isBounded si le dataId attendu n'est pas trouvé mais encadrable et // que la politique gére ce cas de figure // - l'itérateur wDataIt1 est tel que wDataIt1->first < wdataId < (wDataIt1+1)->first // Méthode provenant de la COUPLING_POLICY this->isDataIdConveniant(storedDatas,expectedDataId,isEqual,isBounded,wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 3 ------------------" << std::endl; // L'ordre des différents tests est important if ( isEqual ) { if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 4 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM. // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // C'est EraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion de l'historique dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) { std::cout << "-------- Get : MARK 5 ------------------" << std::endl; std::cout << "-------- Get : Données trouvées à t : " << std::endl; typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit); size_t N = DataManipulator::size(dataToTransmit); std::copy(InIt1, InIt1 + N, std::ostream_iterator< InnerType > (std::cout," ")); std::cout << std::endl; } // Décide de la suppression de certaines instances de données // La donnée contenu dans la structure CORBA et son dataId sont désallouées // Méthode provenant de la COUPLING_POLICY typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas,wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 6 ------------------" << std::endl; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 7 ------------------" << std::endl; //if ( isBounded() && COUPLING_POLICY::template needToProcessBoundedDataId() ) { // Le DataId demandé n'est pas trouvé mais est encadré ET la politique de couplage // implémente une méthode processBoundedDataId capable de générer les données à retourner if ( isBounded ) { // Pour être cohérent avec la politique du bloc précédent // on stocke la paire (dataId,données interpolées ). // CALCIUM ne stockait pas les données interpolées. // Cependant comme les données sont censées être produites // par ordre croissant de DataId, de nouvelles données ne devrait pas améliorer // l'interpolation. if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 8 ------------------" << std::endl; typedef typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> BDI; BDI processBoundedDataId(*this); // typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> processBoundedDataId(*this); //si static BDIP::apply(dataToTransmit,expectedDataId,wDataIt1); //ancienne version template processBoundedDataId<DataManipulator>(dataToTransmit,expectedDataId,wDataIt1); //BDIP processBoundedDataId; processBoundedDataId.apply(dataToTransmit,expectedDataId,wDataIt1); // Il ne peut pas y avoir déjà une clé expectedDataId dans storedDatas (utilisation de la notation [] ) // La nouvelle donnée produite est stockée, ce n'était pas le cas dans CALCIUM // Cette opération n'a peut être pas un caractère générique. // A déplacer en paramètre de la méthode précédente ? ou déléguer ce choix au mode de couplage ? storedDatas[expectedDataId]=dataToTransmit; if (SALOME::VerbosityActivated()) { std::cout << "-------- Get : Données calculées à t : " << std::endl; typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit); size_t N = DataManipulator::size(dataToTransmit); std::copy(InIt1, InIt1 + N, std::ostream_iterator< InnerType > (std::cout," ")); std::cout << std::endl; std::cout << "-------- Get : MARK 9 ------------------" << std::endl; } typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas,wDataIt1); break; } // Délègue au mode de couplage la gestion d'une demande de donnée non disponible // si le port est deconnecté typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); if ( processDisconnect.apply(storedDatas, expectedDataId, wDataIt1) ) continue; // Réception bloquante sur le dataId demandé // Si l'instance de donnée n'est pas trouvee if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 10 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForConvenientDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Get : MARK 11 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Get : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 12 ------------------" << std::endl; } } catch (...) { waitingForConvenientDataId = true; storedDatas_mutex.unlock(); throw; } // Deverouille l'acces a la table storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 13 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType& ti, TimeType tf, TagType tag ) { ti = COUPLING_POLICY::getEffectiveTime(ti,tf); return get(ti,tag); } // Version du next en 0 copy // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas ) template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::next(TimeType &t, TagType &tag ) { typedef typename COUPLING_POLICY::DataId DataId; DataType dataToTransmit; DataId dataId; try { storedDatas_mutex.lock();// Gérer les Exceptions ds le corps de la méthode if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 1 ---lastDataIdSet ("<<lastDataIdSet<<")---------------" << std::endl; typename DataTable::iterator wDataIt1; wDataIt1 = storedDatas.end(); //Recherche le prochain dataId à renvoyer // - lastDataIdset == true indique que lastDataId // contient le dernier DataId renvoyé // - lastDataIdset == false indique que l'on renverra // le premier dataId trouvé // - upper_bound(lastDataId) situe le prochain DataId // à renvoyer // Rem : les données renvoyées ne sont effacées par eraseDataIds // si necessaire if (lastDataIdSet) wDataIt1 = storedDatas.upper_bound(lastDataId); else if ( !storedDatas.empty() ) { lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) { // Délègue au mode de couplage la gestion d'une demande de donnée non disponible // si le port est deconnecté if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) { waitingForAnyDataId = false; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 2 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForAnyDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Next : MARK 3 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Next : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (lastDataIdSet) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 4 ------------------" << std::endl; wDataIt1 = storedDatas.upper_bound(lastDataId); } else { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 5 ------------------" << std::endl; lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 6 ------------------" << std::endl; t = this->getTime( (*wDataIt1).first ); tag = this->getTag ( (*wDataIt1).first ); dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 7 ------------------" << std::endl; lastDataId = (*wDataIt1).first; typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas, wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8 ------------------" << std::endl; } catch (...) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8bis ------------------" << std::endl; waitingForAnyDataId = false; storedDatas_mutex.unlock(); throw; } storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 9 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } #endif
227  // <=> premier emplacement où l'on pourrait insérer notre DataId
228  // <=> en général équivaux à (*wDataIt).first >= currentDataId
229  typename DataTable::iterator wDataIt = storedDatas.lower_bound(currentDataId);
231  std::cout << "-------- Put : MARK 5 ------------------" << std::endl;
232 
233  // On n'a pas trouvé de dataId supérieur au notre ou
234  // on a trouvé une clé > à cet Id
235  if (wDataIt == storedDatas.end() || storedDatas.key_comp()(currentDataId,(*wDataIt).first) ) {
237  std::cout << "-------- Put : MARK 6 ------------------" << std::endl;
238 
239  // Ajoute la donnee dans la table
240  wDataIt = storedDatas.insert(wDataIt, make_pair (currentDataId, data));
241  } else {
242  // Si on n'est pas en fin de liste et qu'il n'y a pas de relation d'ordre strict
243  // entre notre dataId et le DataId pointé c'est qu'ils sont identiques
245  std::cout << "-------- Put : MARK 7 ------------------" << std::endl;
246 
247  // Les données sont remplacées par les nouvelles valeurs
248  // lorsque que le dataId existe déjà DataType old_data = (*wDataIt).second; (*wDataIt).second = data; // Detruit la vieille donnee DataManipulator::delete_data (old_data); } if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 8 ------------------" << std::endl; // Compte le nombre de dataIds à traiter ++nbOfIter; if (SALOME::VerbosityActivated()) { std::cout << "-------- Put : waitingForConvenientDataId : " << waitingForConvenientDataId << "---" << std::endl; std::cout << "-------- Put : waitingForAnyDataId : " << waitingForAnyDataId << "---" << std::endl; std::cout << "-------- Put : currentDataId : " << currentDataId << "---" << std::endl; std::cout << "-------- Put : expectedDataId : " << expectedDataId << "---" << std::endl; std::cout << "-------- Put : MARK 9 ------------------" << std::endl; } // A simplifier mais : // - pas possible de mettre des arguments optionnels à cause // du type itérator qui n'est pas connu (pas de possibilité de déclarer un static ) // - compliquer de créer une méthode sans les paramètres inutiles tout en réutilisant // la méthode initiale car cette dernière ne peut pas être déclarée virtuelle // à cause de ses paramètres templates. Du coup, il faudrait aussi redéfinir la // méthode simplifiée dans les classes définissant une politique // de couplage particulière ... bool dummy1,dummy2; typename DataTable::iterator dummy3; // Par construction, les valeurs de waitingForAnyDataId, waitingForConvenientDataId et de // expectedDataId ne peuvent pas être modifiées pendant le traitement de la boucle // sur les dataIds (à cause du lock utilisé dans la méthode put et les méthodes get ) // rem : Utilisation de l'évaluation gauche droite du logical C or if ( waitingForAnyDataId || ( waitingForConvenientDataId && this->isDataIdConveniant(storedDatas, expectedDataId, dummy1, dummy2, dummy3) ) ) { if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 10 ------------------" << std::endl; //Doit pouvoir réveiller le get ici (a vérifier) expectedDataReceived = true; } } if (expectedDataReceived) { if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 11 ------------------" << std::endl; // si waitingForAnyDataId était positionné, c'est forcément lui qui a activer // expectedDataReceived à true if (waitingForAnyDataId) waitingForAnyDataId = false; else waitingForConvenientDataId = false; // Reveille le thread du destinataire (stoppe son attente) // Ne faudrait-il pas réveiller plutôt tous les threads ? // Celui réveillé ne correspond pas forcément à celui qui demande // cet expectedDataReceived. // Pb1 : cas d'un un get séquentiel et d'un get sur un dataId que l'on vient de recevoir. // Si l'on reveille le mauvais thread, l'autre va attendre indéfiniment ! (sauf timeout) // Pb2 : également si deux attentes de DataIds même différents car on n'en stocke qu'un ! // Conclusion : Pour l'instant on ne gère pas un service multithreadé qui effectue // des lectures simultanées sur le même port ! if (SALOME::VerbosityActivated()) std::cerr << "-------- Put : new datas available ------------------" << std::endl; fflush(stdout);fflush(stderr); cond_instance.signal(); } if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 12 ------------------" << std::endl; // Deverouille l'acces a la table : On peut remonter l'appel au dessus de expected... storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Put : MARK 13 ------------------" << std::endl; fflush(stdout); fflush(stderr); } // Catch les exceptions SALOME//C++ pour la transformer en une exception SALOME//CORBA catch ( const SALOME_Exception & ex ) { // On évite de laisser un mutex storedDatas_mutex.unlock(); THROW_SALOME_CORBA_EXCEPTION(ex.what(), SALOME::INTERNAL_ERROR); } } // erase data before time or tag template < typename DataManipulator, typename COUPLING_POLICY > template <typename TimeType,typename TagType> void GenericPort<DataManipulator, COUPLING_POLICY>::erase(TimeType time, TagType tag, bool before) { typename COUPLING_POLICY::template EraseDataIdBeforeOrAfterTagProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas,time,tag,before); } // Version du Get en 0 copy // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas ) // ( L'utilisateur devra être attentif à la politique de gestion de l'historique // spécifique au mode de couplage car il peut y avoir une suppression potentielle // d'une donnée utilisée directement dans le code utilisateur ) // Le code doit prendre connaissance du transfert de propriété ou non des données // auprès du mode de couplage choisi. template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType time, TagType tag) // REM : Laisse passer toutes les exceptions // En particulier les SALOME_Exceptions qui viennent de la COUPLING_POLICY // Pour déclarer le throw avec l'exception spécifique il faut que je vérifie // qu'un setunexpeted est positionné sinon le C++ arrête tout par appel à terminate { typedef typename COUPLING_POLICY::DataId DataId; // (Pointeur sur séquence) ou valeur.. DataType dataToTransmit ; bool isEqual, isBounded; typedef typename DataManipulator::InnerType InnerType; if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 1 ------------------" << std::endl; expectedDataId = DataId(time,tag); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 2 ------------------" << std::endl; typename DataTable::iterator wDataIt1; try { storedDatas_mutex.lock(); // Gérer les Exceptions ds le corps de la méthode while ( true ) { // Renvoie isEqual si le dataId attendu est trouvé dans storedDatas : // - l'itérateur wDataIt1 pointe alors sur ce dataId // Renvoie isBounded si le dataId attendu n'est pas trouvé mais encadrable et // que la politique gére ce cas de figure // - l'itérateur wDataIt1 est tel que wDataIt1->first < wdataId < (wDataIt1+1)->first // Méthode provenant de la COUPLING_POLICY this->isDataIdConveniant(storedDatas,expectedDataId,isEqual,isBounded,wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 3 ------------------" << std::endl; // L'ordre des différents tests est important if ( isEqual ) { if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 4 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM. // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // C'est EraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion de l'historique dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) { std::cout << "-------- Get : MARK 5 ------------------" << std::endl; std::cout << "-------- Get : Données trouvées à t : " << std::endl; typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit); size_t N = DataManipulator::size(dataToTransmit); std::copy(InIt1, InIt1 + N, std::ostream_iterator< InnerType > (std::cout," ")); std::cout << std::endl; } // Décide de la suppression de certaines instances de données // La donnée contenu dans la structure CORBA et son dataId sont désallouées // Méthode provenant de la COUPLING_POLICY typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas,wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 6 ------------------" << std::endl; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 7 ------------------" << std::endl; //if ( isBounded() && COUPLING_POLICY::template needToProcessBoundedDataId() ) { // Le DataId demandé n'est pas trouvé mais est encadré ET la politique de couplage // implémente une méthode processBoundedDataId capable de générer les données à retourner if ( isBounded ) { // Pour être cohérent avec la politique du bloc précédent // on stocke la paire (dataId,données interpolées ). // CALCIUM ne stockait pas les données interpolées. // Cependant comme les données sont censées être produites // par ordre croissant de DataId, de nouvelles données ne devrait pas améliorer // l'interpolation. if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 8 ------------------" << std::endl; typedef typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> BDI; BDI processBoundedDataId(*this); // typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> processBoundedDataId(*this); //si static BDIP::apply(dataToTransmit,expectedDataId,wDataIt1); //ancienne version template processBoundedDataId<DataManipulator>(dataToTransmit,expectedDataId,wDataIt1); //BDIP processBoundedDataId; processBoundedDataId.apply(dataToTransmit,expectedDataId,wDataIt1); // Il ne peut pas y avoir déjà une clé expectedDataId dans storedDatas (utilisation de la notation [] ) // La nouvelle donnée produite est stockée, ce n'était pas le cas dans CALCIUM // Cette opération n'a peut être pas un caractère générique. // A déplacer en paramètre de la méthode précédente ? ou déléguer ce choix au mode de couplage ? storedDatas[expectedDataId]=dataToTransmit; if (SALOME::VerbosityActivated()) { std::cout << "-------- Get : Données calculées à t : " << std::endl; typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit); size_t N = DataManipulator::size(dataToTransmit); std::copy(InIt1, InIt1 + N, std::ostream_iterator< InnerType > (std::cout," ")); std::cout << std::endl; std::cout << "-------- Get : MARK 9 ------------------" << std::endl; } typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas,wDataIt1); break; } // Délègue au mode de couplage la gestion d'une demande de donnée non disponible // si le port est deconnecté typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); if ( processDisconnect.apply(storedDatas, expectedDataId, wDataIt1) ) continue; // Réception bloquante sur le dataId demandé // Si l'instance de donnée n'est pas trouvee if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 10 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForConvenientDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Get : MARK 11 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Get : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 12 ------------------" << std::endl; } } catch (...) { waitingForConvenientDataId = true; storedDatas_mutex.unlock(); throw; } // Deverouille l'acces a la table storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 13 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType& ti, TimeType tf, TagType tag ) { ti = COUPLING_POLICY::getEffectiveTime(ti,tf); return get(ti,tag); } // Version du next en 0 copy // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas ) template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::next(TimeType &t, TagType &tag ) { typedef typename COUPLING_POLICY::DataId DataId; DataType dataToTransmit; DataId dataId; try { storedDatas_mutex.lock();// Gérer les Exceptions ds le corps de la méthode if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 1 ---lastDataIdSet ("<<lastDataIdSet<<")---------------" << std::endl; typename DataTable::iterator wDataIt1; wDataIt1 = storedDatas.end(); //Recherche le prochain dataId à renvoyer // - lastDataIdset == true indique que lastDataId // contient le dernier DataId renvoyé // - lastDataIdset == false indique que l'on renverra // le premier dataId trouvé // - upper_bound(lastDataId) situe le prochain DataId // à renvoyer // Rem : les données renvoyées ne sont effacées par eraseDataIds // si necessaire if (lastDataIdSet) wDataIt1 = storedDatas.upper_bound(lastDataId); else if ( !storedDatas.empty() ) { lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) { // Délègue au mode de couplage la gestion d'une demande de donnée non disponible // si le port est deconnecté if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) { waitingForAnyDataId = false; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 2 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForAnyDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Next : MARK 3 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Next : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (lastDataIdSet) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 4 ------------------" << std::endl; wDataIt1 = storedDatas.upper_bound(lastDataId); } else { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 5 ------------------" << std::endl; lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 6 ------------------" << std::endl; t = this->getTime( (*wDataIt1).first ); tag = this->getTag ( (*wDataIt1).first ); dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 7 ------------------" << std::endl; lastDataId = (*wDataIt1).first; typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas, wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8 ------------------" << std::endl; } catch (...) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8bis ------------------" << std::endl; waitingForAnyDataId = false; storedDatas_mutex.unlock(); throw; } storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 9 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } #endif
249  DataType old_data = (*wDataIt).second;
250  (*wDataIt).second = data;
251  // Detruit la vieille donnee
252  DataManipulator::delete_data (old_data);
253  }
254 
256  std::cout << "-------- Put : MARK 8 ------------------" << std::endl;
257 
258  // Compte le nombre de dataIds à traiter
259  ++nbOfIter;
260 
262  {
263  std::cout << "-------- Put : waitingForConvenientDataId : " << waitingForConvenientDataId << "---" << std::endl;
264  std::cout << "-------- Put : waitingForAnyDataId : " << waitingForAnyDataId << "---" << std::endl;
265  std::cout << "-------- Put : currentDataId : " << currentDataId << "---" << std::endl;
266  std::cout << "-------- Put : expectedDataId : " << expectedDataId << "---" << std::endl;
267  std::cout << "-------- Put : MARK 9 ------------------" << std::endl;
268  }
269 
270  // A simplifier mais :
271  // - pas possible de mettre des arguments optionnels à cause
272  // du type itérator qui n'est pas connu (pas de possibilité de déclarer un static )
273  // - compliquer de créer une méthode sans les paramètres inutiles tout en réutilisant
274  // la méthode initiale car cette dernière ne peut pas être déclarée virtuelle
275  // à cause de ses paramètres templates. Du coup, il faudrait aussi redéfinir la
276  // méthode simplifiée dans les classes définissant une politique
277  // de couplage particulière ...
278  bool dummy1,dummy2; typename DataTable::iterator dummy3;
279  // Par construction, les valeurs de waitingForAnyDataId, waitingForConvenientDataId et de
280  // expectedDataId ne peuvent pas être modifiées pendant le traitement de la boucle
281  // sur les dataIds (à cause du lock utilisé dans la méthode put et les méthodes get )
282  // rem : Utilisation de l'évaluation gauche droite du logical C or
283  if ( waitingForAnyDataId ||
284  ( waitingForConvenientDataId &&
285  this->isDataIdConveniant(storedDatas, expectedDataId, dummy1, dummy2, dummy3) )
286  )
287  {
289  std::cout << "-------- Put : MARK 10 ------------------" << std::endl;
290 
291  //Doit pouvoir réveiller le get ici (a vérifier)
292  expectedDataReceived = true;
293  }
294  }
295 
296  if (expectedDataReceived) {
298  std::cout << "-------- Put : MARK 11 ------------------" << std::endl;
299 
300  // si waitingForAnyDataId était positionné, c'est forcément lui qui a activer
301  // expectedDataReceived à true
302  if (waitingForAnyDataId)
303  waitingForAnyDataId = false;
304  else
305  waitingForConvenientDataId = false;
306  // Reveille le thread du destinataire (stoppe son attente)
307  // Ne faudrait-il pas réveiller plutôt tous les threads ?
308  // Celui réveillé ne correspond pas forcément à celui qui demande
309  // cet expectedDataReceived.
310  // Pb1 : cas d'un un get séquentiel et d'un get sur un dataId que l'on vient de recevoir.
311  // Si l'on reveille le mauvais thread, l'autre va attendre indéfiniment ! (sauf timeout)
312  // Pb2 : également si deux attentes de DataIds même différents car on n'en stocke qu'un !
313  // Conclusion : Pour l'instant on ne gère pas un service multithreadé qui effectue
314  // des lectures simultanées sur le même port !
316  std::cerr << "-------- Put : new datas available ------------------" << std::endl;
317 
318  fflush(stdout);fflush(stderr);
319  cond_instance.signal();
320  }
321 
323  std::cout << "-------- Put : MARK 12 ------------------" << std::endl;
324 
325  // Deverouille l'acces a la table : On peut remonter l'appel au dessus de expected...
326  storedDatas_mutex.unlock();
327 
329  std::cout << "-------- Put : MARK 13 ------------------" << std::endl;
330 
331  fflush(stdout);
332  fflush(stderr);
333 
334  } // Catch les exceptions SALOME//C++ pour la transformer en une exception SALOME//CORBA
335  catch ( const SALOME_Exception & ex ) {
336  // On évite de laisser un mutex
337  storedDatas_mutex.unlock();
339  }
340 
341 }
342 
343 // erase data before time or tag
344 template < typename DataManipulator, typename COUPLING_POLICY >
345 template <typename TimeType,typename TagType>
346 void
348 {
349  typename COUPLING_POLICY::template EraseDataIdBeforeOrAfterTagProcessor<DataManipulator> processEraseDataId(*this);
350  processEraseDataId.apply(storedDatas,time,tag,before);
351 }
352 
353 // Version du Get en 0 copy
354 // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas )
355 // ( L'utilisateur devra être attentif à la politique de gestion de l'historique
356 // spécifique au mode de couplage car il peut y avoir une suppression potentielle
357 // d'une donnée utilisée directement dans le code utilisateur )
358 // Le code doit prendre connaissance du transfert de propriété ou non des données
359 // auprès du mode de couplage choisi.
360 template < typename DataManipulator, typename COUPLING_POLICY >
361 template < typename TimeType,typename TagType>
362 typename DataManipulator::Type
364  TagType tag)
365 // REM : Laisse passer toutes les exceptions
366 // En particulier les SALOME_Exceptions qui viennent de la COUPLING_POLICY
367 // Pour déclarer le throw avec l'exception spécifique il faut que je vérifie
368 // qu'un setunexpeted est positionné sinon le C++ arrête tout par appel à terminate
369 {
370  typedef typename COUPLING_POLICY::DataId DataId;
371  // (Pointeur sur séquence) ou valeur..
372  DataType dataToTransmit ;
373  bool isEqual, isBounded;
374  typedef typename DataManipulator::InnerType InnerType;
375 
377  std::cout << "-------- Get : MARK 1 ------------------" << std::endl;
378 
379  expectedDataId = DataId(time,tag);
381  std::cout << "-------- Get : MARK 2 ------------------" << std::endl;
382 
383  typename DataTable::iterator wDataIt1;
384 
385  try {
386  storedDatas_mutex.lock(); // Gérer les Exceptions ds le corps de la méthode
387 
388  while ( true ) {
389 
390  // Renvoie isEqual si le dataId attendu est trouvé dans storedDatas :
391  // - l'itérateur wDataIt1 pointe alors sur ce dataId
392  // Renvoie isBounded si le dataId attendu n'est pas trouvé mais encadrable et
393  // que la politique gére ce cas de figure
394  // - l'itérateur wDataIt1 est tel que wDataIt1->first < wdataId < (wDataIt1+1)->first
395  // Méthode provenant de la COUPLING_POLICY
396  this->isDataIdConveniant(storedDatas,expectedDataId,isEqual,isBounded,wDataIt1);
398  std::cout << "-------- Get : MARK 3 ------------------" << std::endl;
399 
400  // L'ordre des différents tests est important
401  if ( isEqual ) {
403  std::cout << "-------- Get : MARK 4 ------------------" << std::endl;
404 
405  // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM.
406  // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
407  // C'est EraseDataId qui choisi ou non de supprimer la donnée
408  // Du coup interaction potentielle entre le 0 copy et gestion de l'historique
409  dataToTransmit = (*wDataIt1).second;
410 
412  {
413  std::cout << "-------- Get : MARK 5 ------------------" << std::endl;
414  std::cout << "-------- Get : Données trouvées à t : " << std::endl;
415  typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit);
416  size_t N = DataManipulator::size(dataToTransmit);
417  std::copy(InIt1, InIt1 + N,
418  std::ostream_iterator< InnerType > (std::cout," "));
419  std::cout << std::endl;
420  }
421 
422  // Décide de la suppression de certaines instances de données
423  // La donnée contenu dans la structure CORBA et son dataId sont désallouées
424  // Méthode provenant de la COUPLING_POLICY
425  typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
426  processEraseDataId.apply(storedDatas,wDataIt1);
428  std::cout << "-------- Get : MARK 6 ------------------" << std::endl;
429 
430  break;
431  }
432 
434  std::cout << "-------- Get : MARK 7 ------------------" << std::endl;
435 
436  //if ( isBounded() && COUPLING_POLICY::template needToProcessBoundedDataId() ) {
437  // Le DataId demandé n'est pas trouvé mais est encadré ET la politique de couplage
438  // implémente une méthode processBoundedDataId capable de générer les données à retourner
439  if ( isBounded ) {
440  // Pour être cohérent avec la politique du bloc précédent
441  // on stocke la paire (dataId,données interpolées ).
442  // CALCIUM ne stockait pas les données interpolées.
443  // Cependant comme les données sont censées être produites
444  // par ordre croissant de DataId, de nouvelles données ne devrait pas améliorer
445  // l'interpolation.
447  std::cout << "-------- Get : MARK 8 ------------------" << std::endl;
448 
449  typedef typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> BDI;
450  BDI processBoundedDataId(*this);
451  // typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> processBoundedDataId(*this);
452  //si static BDIP::apply(dataToTransmit,expectedDataId,wDataIt1);
453  //ancienne version template processBoundedDataId<DataManipulator>(dataToTransmit,expectedDataId,wDataIt1);
454  //BDIP processBoundedDataId;
455  processBoundedDataId.apply(dataToTransmit,expectedDataId,wDataIt1);
456 
457  // Il ne peut pas y avoir déjà une clé expectedDataId dans storedDatas (utilisation de la notation [] )
458  // La nouvelle donnée produite est stockée, ce n'était pas le cas dans CALCIUM
459  // Cette opération n'a peut être pas un caractère générique.
460  // A déplacer en paramètre de la méthode précédente ? ou déléguer ce choix au mode de couplage ?
461  storedDatas[expectedDataId]=dataToTransmit;
462 
464  {
465  std::cout << "-------- Get : Données calculées à t : " << std::endl;
466  typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit);
467  size_t N = DataManipulator::size(dataToTransmit);
468 
469  std::copy(InIt1, InIt1 + N,
470  std::ostream_iterator< InnerType > (std::cout," "));
471  std::cout << std::endl;
472  std::cout << "-------- Get : MARK 9 ------------------" << std::endl;
473  }
474 
475  typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
476  processEraseDataId.apply(storedDatas,wDataIt1);
477 
478  break;
479  }
480 
481  // Délègue au mode de couplage la gestion d'une demande de donnée non disponible
482  // si le port est deconnecté typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); if ( processDisconnect.apply(storedDatas, expectedDataId, wDataIt1) ) continue; // Réception bloquante sur le dataId demandé // Si l'instance de donnée n'est pas trouvee if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 10 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForConvenientDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Get : MARK 11 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Get : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 12 ------------------" << std::endl; } } catch (...) { waitingForConvenientDataId = true; storedDatas_mutex.unlock(); throw; } // Deverouille l'acces a la table storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 13 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType& ti, TimeType tf, TagType tag ) { ti = COUPLING_POLICY::getEffectiveTime(ti,tf); return get(ti,tag); } // Version du next en 0 copy // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas ) template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::next(TimeType &t, TagType &tag ) { typedef typename COUPLING_POLICY::DataId DataId; DataType dataToTransmit; DataId dataId; try { storedDatas_mutex.lock();// Gérer les Exceptions ds le corps de la méthode if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 1 ---lastDataIdSet ("<<lastDataIdSet<<")---------------" << std::endl; typename DataTable::iterator wDataIt1; wDataIt1 = storedDatas.end(); //Recherche le prochain dataId à renvoyer // - lastDataIdset == true indique que lastDataId // contient le dernier DataId renvoyé // - lastDataIdset == false indique que l'on renverra // le premier dataId trouvé // - upper_bound(lastDataId) situe le prochain DataId // à renvoyer // Rem : les données renvoyées ne sont effacées par eraseDataIds // si necessaire if (lastDataIdSet) wDataIt1 = storedDatas.upper_bound(lastDataId); else if ( !storedDatas.empty() ) { lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) { // Délègue au mode de couplage la gestion d'une demande de donnée non disponible // si le port est deconnecté if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) { waitingForAnyDataId = false; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 2 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForAnyDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Next : MARK 3 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Next : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (lastDataIdSet) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 4 ------------------" << std::endl; wDataIt1 = storedDatas.upper_bound(lastDataId); } else { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 5 ------------------" << std::endl; lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 6 ------------------" << std::endl; t = this->getTime( (*wDataIt1).first ); tag = this->getTag ( (*wDataIt1).first ); dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 7 ------------------" << std::endl; lastDataId = (*wDataIt1).first; typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas, wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8 ------------------" << std::endl; } catch (...) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8bis ------------------" << std::endl; waitingForAnyDataId = false; storedDatas_mutex.unlock(); throw; } storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 9 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } #endif
483  typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this);
484  if ( processDisconnect.apply(storedDatas, expectedDataId, wDataIt1) ) continue;
485 
486  // Réception bloquante sur le dataId demandé // Si l'instance de donnée n'est pas trouvee if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 10 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForConvenientDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Get : MARK 11 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Get : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 12 ------------------" << std::endl; } } catch (...) { waitingForConvenientDataId = true; storedDatas_mutex.unlock(); throw; } // Deverouille l'acces a la table storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Get : MARK 13 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType& ti, TimeType tf, TagType tag ) { ti = COUPLING_POLICY::getEffectiveTime(ti,tf); return get(ti,tag); } // Version du next en 0 copy // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas ) template < typename DataManipulator, typename COUPLING_POLICY > template < typename TimeType,typename TagType> typename DataManipulator::Type GenericPort<DataManipulator, COUPLING_POLICY>::next(TimeType &t, TagType &tag ) { typedef typename COUPLING_POLICY::DataId DataId; DataType dataToTransmit; DataId dataId; try { storedDatas_mutex.lock();// Gérer les Exceptions ds le corps de la méthode if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 1 ---lastDataIdSet ("<<lastDataIdSet<<")---------------" << std::endl; typename DataTable::iterator wDataIt1; wDataIt1 = storedDatas.end(); //Recherche le prochain dataId à renvoyer // - lastDataIdset == true indique que lastDataId // contient le dernier DataId renvoyé // - lastDataIdset == false indique que l'on renverra // le premier dataId trouvé // - upper_bound(lastDataId) situe le prochain DataId // à renvoyer // Rem : les données renvoyées ne sont effacées par eraseDataIds // si necessaire if (lastDataIdSet) wDataIt1 = storedDatas.upper_bound(lastDataId); else if ( !storedDatas.empty() ) { lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) { // Délègue au mode de couplage la gestion d'une demande de donnée non disponible // si le port est deconnecté if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) { waitingForAnyDataId = false; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 2 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForAnyDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Next : MARK 3 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Next : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (lastDataIdSet) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 4 ------------------" << std::endl; wDataIt1 = storedDatas.upper_bound(lastDataId); } else { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 5 ------------------" << std::endl; lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 6 ------------------" << std::endl; t = this->getTime( (*wDataIt1).first ); tag = this->getTag ( (*wDataIt1).first ); dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 7 ------------------" << std::endl; lastDataId = (*wDataIt1).first; typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas, wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8 ------------------" << std::endl; } catch (...) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8bis ------------------" << std::endl; waitingForAnyDataId = false; storedDatas_mutex.unlock(); throw; } storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 9 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } #endif
487  // Si l'instance de donnée n'est pas trouvee
489  std::cout << "-------- Get : MARK 10 ------------------" << std::endl;
490 
491  //Positionné à faux dans la méthode put
492  waitingForConvenientDataId = true;
494  {
495  std::cout << "-------- Get : MARK 11 ------------------" << std::endl;
496 
497  // Ici on attend que la méthode put recoive la donnée
498  std::cout << "-------- Get : waiting datas ------------------" << std::endl;
499  }
500 
501  fflush(stdout);fflush(stderr);
502  unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut;
503  if(rs==0)
504  cond_instance.wait();
505  else
506  {
507  //Timed wait on omni condition
508  omni_thread::get_time(&ts,&tns, rs,0);
509  int success=cond_instance.timedwait(ts,tns);
510  if(!success)
511  {
512  // Waiting too long probably blocking
513  std::stringstream msg;
514  msg<<"Timeout ("<<rs<<" s) exceeded";
515  Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str());
516  throw DSC_Exception(msg.str());
517  }
518  }
519 
521  std::cout << "-------- Get : MARK 12 ------------------" << std::endl;
522  }
523  } catch (...) {
524  waitingForConvenientDataId = true;
525  storedDatas_mutex.unlock();
526  throw;
527  }
528 
529  // Deverouille l'acces a la table
530  storedDatas_mutex.unlock();
532  std::cout << "-------- Get : MARK 13 ------------------" << std::endl;
533 
534  // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM
535  // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
536  // c'est eraseDataId qui choisi ou non de supprimer la donnée
537  // Du coup interaction potentielle entre le 0 copy et gestion des niveaux
538  return dataToTransmit;
539 
540 }
541 
542 template < typename DataManipulator, typename COUPLING_POLICY >
543 template < typename TimeType,typename TagType>
544 typename DataManipulator::Type
546  TimeType tf,
547  TagType tag ) {
548  ti = COUPLING_POLICY::getEffectiveTime(ti,tf);
549  return get(ti,tag);
550 }
551 
552 
553 // Version du next en 0 copy
554 // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas )
555 template < typename DataManipulator, typename COUPLING_POLICY >
556 template < typename TimeType,typename TagType>
557 typename DataManipulator::Type
559  TagType &tag ) {
560 
561  typedef typename COUPLING_POLICY::DataId DataId;
562 
563  DataType dataToTransmit;
564  DataId dataId;
565 
566  try {
567  storedDatas_mutex.lock();// Gérer les Exceptions ds le corps de la méthode
568 
570  std::cout << "-------- Next : MARK 1 ---lastDataIdSet ("<<lastDataIdSet<<")---------------" << std::endl;
571 
572  typename DataTable::iterator wDataIt1;
573  wDataIt1 = storedDatas.end();
574 
575  //Recherche le prochain dataId à renvoyer
576  // - lastDataIdset == true indique que lastDataId
577  // contient le dernier DataId renvoyé // - lastDataIdset == false indique que l'on renverra // le premier dataId trouvé // - upper_bound(lastDataId) situe le prochain DataId // à renvoyer // Rem : les données renvoyées ne sont effacées par eraseDataIds // si necessaire if (lastDataIdSet) wDataIt1 = storedDatas.upper_bound(lastDataId); else if ( !storedDatas.empty() ) { lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) { // Délègue au mode de couplage la gestion d'une demande de donnée non disponible // si le port est deconnecté if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) { waitingForAnyDataId = false; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 2 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForAnyDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Next : MARK 3 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Next : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (lastDataIdSet) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 4 ------------------" << std::endl; wDataIt1 = storedDatas.upper_bound(lastDataId); } else { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 5 ------------------" << std::endl; lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 6 ------------------" << std::endl; t = this->getTime( (*wDataIt1).first ); tag = this->getTag ( (*wDataIt1).first ); dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 7 ------------------" << std::endl; lastDataId = (*wDataIt1).first; typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas, wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8 ------------------" << std::endl; } catch (...) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8bis ------------------" << std::endl; waitingForAnyDataId = false; storedDatas_mutex.unlock(); throw; } storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 9 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } #endif
578  // - lastDataIdset == false indique que l'on renverra
579  // le premier dataId trouvé // - upper_bound(lastDataId) situe le prochain DataId // à renvoyer // Rem : les données renvoyées ne sont effacées par eraseDataIds // si necessaire if (lastDataIdSet) wDataIt1 = storedDatas.upper_bound(lastDataId); else if ( !storedDatas.empty() ) { lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this); while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) { // Délègue au mode de couplage la gestion d'une demande de donnée non disponible // si le port est deconnecté if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) { waitingForAnyDataId = false; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 2 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForAnyDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Next : MARK 3 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Next : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (lastDataIdSet) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 4 ------------------" << std::endl; wDataIt1 = storedDatas.upper_bound(lastDataId); } else { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 5 ------------------" << std::endl; lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 6 ------------------" << std::endl; t = this->getTime( (*wDataIt1).first ); tag = this->getTag ( (*wDataIt1).first ); dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 7 ------------------" << std::endl; lastDataId = (*wDataIt1).first; typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas, wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8 ------------------" << std::endl; } catch (...) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8bis ------------------" << std::endl; waitingForAnyDataId = false; storedDatas_mutex.unlock(); throw; } storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 9 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } #endif
580  // - upper_bound(lastDataId) situe le prochain DataId
581  // à renvoyer
582  // Rem : les données renvoyées ne sont effacées par eraseDataIds
583  // si necessaire
584  if (lastDataIdSet)
585  wDataIt1 = storedDatas.upper_bound(lastDataId);
586  else if ( !storedDatas.empty() ) {
587  lastDataIdSet = true;
588  wDataIt1 = storedDatas.begin();
589  }
590 
591  typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this);
592 
593  while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) {
594 
595  // Délègue au mode de couplage la gestion d'une demande de donnée non disponible
596  // si le port est deconnecté if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) { waitingForAnyDataId = false; break; } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 2 ------------------" << std::endl; //Positionné à faux dans la méthode put waitingForAnyDataId = true; if (SALOME::VerbosityActivated()) { std::cout << "-------- Next : MARK 3 ------------------" << std::endl; // Ici on attend que la méthode put recoive la donnée std::cout << "-------- Next : waiting datas ------------------" << std::endl; } fflush(stdout);fflush(stderr); unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut; if(rs==0) cond_instance.wait(); else { //Timed wait on omni condition omni_thread::get_time(&ts,&tns, rs,0); int success=cond_instance.timedwait(ts,tns); if(!success) { // Waiting too long probably blocking std::stringstream msg; msg<<"Timeout ("<<rs<<" s) exceeded"; Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str()); throw DSC_Exception(msg.str()); } } if (lastDataIdSet) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 4 ------------------" << std::endl; wDataIt1 = storedDatas.upper_bound(lastDataId); } else { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 5 ------------------" << std::endl; lastDataIdSet = true; wDataIt1 = storedDatas.begin(); } } if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 6 ------------------" << std::endl; t = this->getTime( (*wDataIt1).first ); tag = this->getTag ( (*wDataIt1).first ); dataToTransmit = (*wDataIt1).second; if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 7 ------------------" << std::endl; lastDataId = (*wDataIt1).first; typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this); processEraseDataId.apply(storedDatas, wDataIt1); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8 ------------------" << std::endl; } catch (...) { if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 8bis ------------------" << std::endl; waitingForAnyDataId = false; storedDatas_mutex.unlock(); throw; } storedDatas_mutex.unlock(); if (SALOME::VerbosityActivated()) std::cout << "-------- Next : MARK 9 ------------------" << std::endl; // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent // c'est eraseDataId qui choisi ou non de supprimer la donnée // Du coup interaction potentielle entre le 0 copy et gestion des niveaux return dataToTransmit; } #endif
597  if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) {
598  waitingForAnyDataId = false; break;
599  }
600 
602  std::cout << "-------- Next : MARK 2 ------------------" << std::endl;
603 
604  //Positionné à faux dans la méthode put
605  waitingForAnyDataId = true;
606 
608  {
609  std::cout << "-------- Next : MARK 3 ------------------" << std::endl;
610  // Ici on attend que la méthode put recoive la donnée
611  std::cout << "-------- Next : waiting datas ------------------" << std::endl;
612  }
613 
614  fflush(stdout);fflush(stderr);
615  unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut;
616  if(rs==0)
617  cond_instance.wait();
618  else
619  {
620  //Timed wait on omni condition
621  omni_thread::get_time(&ts,&tns, rs,0);
622  int success=cond_instance.timedwait(ts,tns);
623  if(!success)
624  {
625  // Waiting too long probably blocking
626  std::stringstream msg;
627  msg<<"Timeout ("<<rs<<" s) exceeded";
628  Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str());
629  throw DSC_Exception(msg.str());
630  }
631  }
632 
633  if (lastDataIdSet) {
635  std::cout << "-------- Next : MARK 4 ------------------" << std::endl;
636 
637  wDataIt1 = storedDatas.upper_bound(lastDataId);
638  } else {
640  std::cout << "-------- Next : MARK 5 ------------------" << std::endl;
641 
642  lastDataIdSet = true;
643  wDataIt1 = storedDatas.begin();
644  }
645  }
646 
648  std::cout << "-------- Next : MARK 6 ------------------" << std::endl;
649 
650  t = this->getTime( (*wDataIt1).first );
651  tag = this->getTag ( (*wDataIt1).first );
652  dataToTransmit = (*wDataIt1).second;
653 
655  std::cout << "-------- Next : MARK 7 ------------------" << std::endl;
656 
657  lastDataId = (*wDataIt1).first;
658 
659  typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
660  processEraseDataId.apply(storedDatas, wDataIt1);
661 
663  std::cout << "-------- Next : MARK 8 ------------------" << std::endl;
664  } catch (...) {
666  std::cout << "-------- Next : MARK 8bis ------------------" << std::endl;
667 
668  waitingForAnyDataId = false;
669  storedDatas_mutex.unlock();
670  throw;
671  }
672  storedDatas_mutex.unlock();
673 
675  std::cout << "-------- Next : MARK 9 ------------------" << std::endl;
676 
677  // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM
678  // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
679  // c'est eraseDataId qui choisi ou non de supprimer la donnée
680  // Du coup interaction potentielle entre le 0 copy et gestion des niveaux
681  return dataToTransmit;
682 
683 }
684 
685 #endif
#define THROW_SALOME_CORBA_EXCEPTION(chain, typex)
To raise a CORBA exception from a CORBA servant.
Definition: Utils_CorbaException.hxx:40
static void writeEvent(const char *request, const std::string &containerName, const char *instance_name, const char *port_name, const char *error, const char *message)
Write a record in the trace file.
Definition: DSC_interface.cxx:478
Definition: GenericPort.hxx:61
DataId expectedDataId
Definition: GenericPort.hxx:93
void close(PortableServer::POA_var poa, PortableServer::ObjectId_var id)
Definition: GenericPort.hxx:121
omni_mutex storedDatas_mutex
Definition: GenericPort.hxx:98
GenericPort()
Definition: GenericPort.hxx:105
DataManipulator::CorbaInType CorbaInDataType
Definition: GenericPort.hxx:65
bool lastDataIdSet
Definition: GenericPort.hxx:96
omni_condition cond_instance
Definition: GenericPort.hxx:100
std::map< DataId, DataType > DataTable
Definition: GenericPort.hxx:82
bool waitingForConvenientDataId
Definition: GenericPort.hxx:88
void put(CorbaInDataType data, TimeType time, TagType tag)
Definition: GenericPort.hxx:155
void erase(TimeType time, TagType tag, bool before)
Definition: GenericPort.hxx:347
void wakeupWaiting()
Definition: GenericPort.hxx:129
DataType next(TimeType &t, TagType &tag)
DataType get(TimeType time, TagType tag)
COUPLING_POLICY::DataId DataId
Definition: GenericPort.hxx:81
DataManipulator::Type DataType
Definition: GenericPort.hxx:64
DataType get(TimeType &ti, TimeType tf, TagType tag=0)
bool waitingForAnyDataId
Definition: GenericPort.hxx:90
virtual ~GenericPort()
Definition: GenericPort.hxx:110
DataTable storedDatas
Definition: GenericPort.hxx:85
DataId lastDataId
Definition: GenericPort.hxx:95
Definition: Utils_SALOME_Exception.hxx:66
virtual const char * what(void) const noexcept
Definition: Utils_SALOME_Exception.cxx:72
static long dscTimeOut
Definition: Superv_Component_i.hxx:251
poa
Definition: SALOME_ContainerPy.py:377
stdout
Definition: SALOME_ContainerPy.py:373
@ INTERNAL_ERROR
Application level problem, irrecoverable.
Definition: SALOME_Exception.idl:52
bool VerbosityActivated()
Called by any log message macros to decide about log output in Release and Debug mode dynamically rel...
Definition: libSALOMELog.cxx:48
string msg
Definition: TestMinimalExample.py:168
def dump(filename)
Definition: pythfilter.py:368
def copy(src, dst)
Definition: pythonpath_reduction.py:35
Definition: DSC_Exception.hxx:94
double TagType
Definition: testAdjacentPredicate.cxx:53
std::pair< TimeType, TagType > DataId
Definition: testAdjacentPredicate.cxx:54
int TimeType
Definition: testAdjacentPredicate.cxx:52