SALOME documentation central

src/DSC/DSC_User/Datastream/GenericPort.hxx

00001 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 //  This library is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU Lesser General Public
00008 //  License as published by the Free Software Foundation; either
00009 //  version 2.1 of the License.
00010 //
00011 //  This library is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 //  Lesser General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU Lesser General Public
00017 //  License along with this library; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 //  File   : GenericPort.hxx
00023 //  Author : Eric Fayolle (EDF)
00024 //  Module : KERNEL
00025 // Modified by : $LastChangedBy$
00026 // Date        : $LastChangedDate: 2007-02-28 15:26:32 +0100 (mer, 28 fév 2007) $
00027 // Id          : $Id$
00028 //
00029 #ifndef _GENERIC_PORT_HXX_
00030 #define _GENERIC_PORT_HXX_
00031 
00032 #include "CorbaTypeManipulator.hxx"
00033 
00034 #include "Superv_Component_i.hxx"
00035 // SALOME CORBA Exception
00036 #include "Utils_CorbaException.hxx"
00037 // SALOME C++   Exception
00038 #include "Utils_SALOME_Exception.hxx"
00039 #include "DSC_Exception.hxx"
00040 #include "utilities.h"
00041 
00042 #include <iostream>
00043 #include <map>
00044 
00045 // Inclusions pour l'affichage
00046 #include <algorithm>
00047 #include <iterator>
00048 
00049 //#define MYDEBUG
00050 
00051 // Classe GenericPort
00052 // --------------------------------
00053 //
00054 // Definition: Implemente un port de type "data-stream"
00055 // Cette implémentation gère tous les types de données définies par DataManipulator::type
00056 // Ce port est soumis à une politique d'itération sur les identificateurs de données (DataId)
00057 // Un identificateur de données est construit à partir d'un ou plusieurs paramètres de la méthode put
00058 // tels que :  une date, une itération, un pas de temps ou une combinaison de ces paramètres.
00059 
00060 template < typename DataManipulator, class COUPLING_POLICY >
00061 class GenericPort : public COUPLING_POLICY  {
00062 public:
00063   // Type de données manipulés 
00064   typedef typename DataManipulator::Type         DataType;
00065   typedef typename DataManipulator::CorbaInType  CorbaInDataType;
00066 
00067   GenericPort(); 
00068   virtual ~GenericPort();
00069 
00070   template <typename TimeType,typename TagType> void     put(CorbaInDataType data,  TimeType time, TagType tag);
00071   template <typename TimeType,typename TagType> DataType get(TimeType time, TagType tag);
00072   template <typename TimeType,typename TagType> DataType get(TimeType& ti, TimeType tf, TagType tag = 0);
00073   template <typename TimeType,typename TagType> DataType next(TimeType &t, TagType  &tag );
00074   void      close (PortableServer::POA_var poa, PortableServer::ObjectId_var id);
00075   void wakeupWaiting();
00076 
00077 private:
00078 
00079   // Type identifiant une instance de donnee. Exemple (time,tag) 
00080   typedef typename COUPLING_POLICY::DataId DataId;
00081   typedef std::map< DataId, DataType>      DataTable;
00082 
00083   // Stockage des donnees recues et non encore distribuées
00084   DataTable storedDatas ;
00085 
00086   // Indicateur que le destinataire attend une instance particuliere de données
00087   bool     waitingForConvenientDataId;
00088   // Indicateur que le destinataire attend n'importe qu'elle instance de données
00089   bool     waitingForAnyDataId;
00090 
00091   // Identificateur de la donné que le destinataire (propriétaire du port) attend
00092   DataId   expectedDataId ;
00093   // Sauvegarde du DataId courant pour la méthode next 
00094   DataId   lastDataId;
00095   bool     lastDataIdSet;
00096   // Exclusion mutuelle d'acces a la table des données reçues
00097   omni_mutex     storedDatas_mutex;
00098   // Condition d'attente d'une instance (Le processus du Get attend la condition declaree par le processus Put)
00099   omni_condition cond_instance;
00100 
00101 };
00102 
00103 template < typename DataManipulator, typename COUPLING_POLICY >
00104 GenericPort<DataManipulator, COUPLING_POLICY >::GenericPort() :
00105   cond_instance(& this->storedDatas_mutex),waitingForConvenientDataId(false),
00106   waitingForAnyDataId(false),lastDataIdSet(false) {}
00107 
00108 template < typename DataManipulator, typename COUPLING_POLICY>
00109 GenericPort<DataManipulator, COUPLING_POLICY>::~GenericPort() {
00110   typename DataTable::iterator it;
00111   for (it=storedDatas.begin(); it!=storedDatas.end(); ++it) {
00112 #ifdef MYDEBUG
00113     std::cerr << "~GenericPort() : destruction de la donnnée associée au DataId :"<<  (*it).first << std::endl;
00114 #endif
00115     DataManipulator::delete_data( (*it).second );
00116   }
00117 }
00118 
00119 template < typename DataManipulator, typename COUPLING_POLICY> void 
00120 GenericPort<DataManipulator, COUPLING_POLICY>::close (PortableServer::POA_var poa, 
00121                                                       PortableServer::ObjectId_var id) {
00122   // Ferme le port en supprimant le servant
00123   // La desactivation du servant du POA provoque sa suppression
00124   poa->deactivate_object (id);
00125 }
00126 
00127 template < typename DataManipulator, typename COUPLING_POLICY> void
00128 GenericPort<DataManipulator, COUPLING_POLICY>::wakeupWaiting()
00129 {
00130 #ifdef MYDEBUG
00131   std::cout << "-------- wakeupWaiting ------------------" << std::endl;
00132 #endif
00133   storedDatas_mutex.lock();
00134   if (waitingForAnyDataId || waitingForConvenientDataId) {
00135 #ifdef MYDEBUG
00136     std::cout << "-------- wakeupWaiting:signal --------" << std::endl;
00137     std::cout << std::flush;
00138 #endif
00139     cond_instance.signal();
00140    }
00141   storedDatas_mutex.unlock();
00142 
00143 }
00144 
00145 /* Methode put_generique
00146  *
00147  * Stocke en memoire une instance de donnee (pointeur) que l'emetteur donne a l'intention du destinataire.
00148  * Reveille le destinataire, si il y a lieu.
00149  */
00150 template < typename DataManipulator, typename COUPLING_POLICY>
00151 template < typename TimeType,typename TagType>
00152 void GenericPort<DataManipulator, COUPLING_POLICY>::put(CorbaInDataType dataParam, 
00153                                                         TimeType time, 
00154                                                         TagType  tag) {
00155   fflush(stdout);
00156   fflush(stderr);
00157   try {
00158 #ifdef MYDEBUG
00159     // Affichage des donnees pour DEBUGging
00160     std::cerr << "parametres emis: " << time << ", " << tag << std::endl;
00161     DataManipulator::dump(dataParam);
00162 #endif
00163   
00164     // L'intérêt des paramètres time et tag pour ce port est décidé dans la politique de couplage
00165     // Il est possible de filtrer en prenant en compte uniquement un paramètre time/tag ou les deux
00166     // Il est également possible de convertir les données recues ou bien de les dupliquer
00167     // pour plusieurs  valeurs de time et/ou tag (d'où la notion de container dans la politique de couplage)
00168     typedef typename COUPLING_POLICY::DataIdContainer DataIdContainer;  
00169     typedef typename COUPLING_POLICY::DataId          DataId;
00170 
00171     DataId          dataId(time,tag);
00172     // Effectue les traitements spécifiques à la politique de couplage 
00173     // pour construire une liste d'ids (par filtrage, conversion ...)
00174     // DataIdContainer dataIds(dataId,*(static_cast<const COUPLING_POLICY *>(this)));   
00175     DataIdContainer dataIds(dataId, *this);   
00176 
00177     typename DataIdContainer::iterator dataIdIt = dataIds.begin();
00178 
00179     bool expectedDataReceived = false;
00180 
00181 #ifdef MYDEBUG
00182     std::cout << "-------- Put : MARK 1 ------------------" << std::endl;
00183 #endif
00184     if ( dataIds.empty() ) return;
00185 #ifdef MYDEBUG
00186     std::cout << "-------- Put : MARK 1bis ------------------" << std::endl;
00187 #endif
00188 
00189     // Recupere les donnees venant de l'ORB et relâche les structures CORBA 
00190     // qui n'auraient plus cours en sortie de méthode put
00191     DataType data = DataManipulator::get_data(dataParam);
00192 
00193 
00194     int nbOfIter = 0;
00195 
00196 #ifdef MYDEBUG
00197     std::cout << "-------- Put : MARK 2 ------ "<< (dataIdIt == dataIds.end()) << "------------" << std::endl;
00198     std::cout << "-------- Put : MARK 2bis "<< (*dataIdIt) <<"------------------" << std::endl;
00199 #endif
00200     storedDatas_mutex.lock();
00201 
00202     for (;dataIdIt != dataIds.end();++dataIdIt) {
00203 
00204 #ifdef MYDEBUG
00205       std::cout << "-------- Put : MARK 3 ------------------" << std::endl;
00206 #endif
00207       // Duplique l'instance de donnée pour les autres dataIds 
00208       if (nbOfIter > 0) data = DataManipulator::clone(data);
00209 #ifdef MYDEBUG
00210       std::cout << "-------- Put : MARK 3bis -----"<< dataIdIt.operator*() <<"------------" << std::endl;
00211 #endif
00212     
00213       DataId currentDataId=*dataIdIt;
00214 
00215 #ifdef MYDEBUG
00216       std::cerr << "processing dataId : "<< currentDataId << std::endl;
00217 
00218       std::cout << "-------- Put : MARK 4 ------------------" << std::endl;
00219 #endif
00220  
00221       // Ajoute l'instance de la donnee a sa place dans la table de données
00222       // ou remplace une instance précédente si elle existe
00223     
00224       // Recherche la première clé telle quelle ne soit pas <  currentDataId
00225       // pour celà l'opérateur de comparaison storedDatas.key_comp() est utilisé
00226       // <=> premier emplacement où l'on pourrait insérer notre DataId
00227       // <=> en général équivaux à (*wDataIt).first >= currentDataId
00228       typename DataTable::iterator wDataIt = storedDatas.lower_bound(currentDataId);
00229 #ifdef MYDEBUG
00230       std::cout << "-------- Put : MARK 5 ------------------" << std::endl;
00231 #endif
00232 
00233       // On n'a pas trouvé de dataId supérieur au notre ou 
00234       // on a trouvé une clé >  à cet Id          
00235       if (wDataIt == storedDatas.end() || storedDatas.key_comp()(currentDataId,(*wDataIt).first) ) {
00236 #ifdef MYDEBUG
00237         std::cout << "-------- Put : MARK 6 ------------------" << std::endl;
00238 #endif
00239         // Ajoute la donnee dans la table
00240         wDataIt = storedDatas.insert(wDataIt, make_pair (currentDataId, data));
00241       } else  {
00242         // Si on n'est pas en fin de liste et qu'il n'y a pas de relation d'ordre strict
00243         // entre notre dataId et le DataId pointé c'est qu'ils sont identiques
00244 #ifdef MYDEBUG
00245         std::cout << "-------- Put : MARK 7 ------------------" << std::endl;
00246 #endif
00247         // Les données sont remplacées par les nouvelles valeurs
00248         // lorsque que le dataId existe déjà
00249         DataType old_data = (*wDataIt).second;
00250         (*wDataIt).second = data;
00251         // Detruit la vieille donnee
00252         DataManipulator::delete_data (old_data);
00253       }
00254   
00255 #ifdef MYDEBUG
00256       std::cout << "-------- Put : MARK 8 ------------------" << std::endl;
00257 #endif
00258       // Compte le nombre de dataIds à traiter
00259       ++nbOfIter;
00260 
00261 #ifdef MYDEBUG
00262       std::cout << "-------- Put : waitingForConvenientDataId : " << waitingForConvenientDataId <<"---" << std::endl;
00263       std::cout << "-------- Put : waitingForAnyDataId : " << waitingForAnyDataId <<"---" << std::endl;
00264       std::cout << "-------- Put : currentDataId  : " << currentDataId <<"---" << std::endl;
00265       std::cout << "-------- Put : expectedDataId : " << expectedDataId <<"---" << std::endl;
00266       std::cout << "-------- Put : MARK 9 ------------------" << std::endl;
00267 #endif
00268 
00269       // A simplifier mais :
00270       // - pas possible de mettre des arguments optionnels à cause
00271       //   du type itérator qui n'est pas connu (pas de possibilité de déclarer un static )
00272       // - compliquer de créer une méthode sans les paramètres inutiles tout en réutilisant
00273       //   la méthode initiale car cette dernière ne peut pas être déclarée virtuelle 
00274       //   à cause de ses paramètres templates. Du coup, il faudrait aussi redéfinir la
00275       //   méthode simplifiée dans les classes définissant une politique 
00276       //   de couplage particulière ...
00277       bool dummy1,dummy2; typename DataTable::iterator dummy3;
00278       // Par construction, les valeurs de waitingForAnyDataId, waitingForConvenientDataId et de 
00279       // expectedDataId ne peuvent pas être modifiées pendant le traitement de la boucle
00280       // sur les dataIds (à cause du lock utilisé dans la méthode put et les méthodes get )
00281       // rem : Utilisation de l'évaluation gauche droite du logical C or
00282       if ( waitingForAnyDataId || 
00283            ( waitingForConvenientDataId && 
00284              isDataIdConveniant(storedDatas, expectedDataId, dummy1, dummy2, dummy3) ) 
00285            ) {
00286 #ifdef MYDEBUG
00287         std::cout << "-------- Put : MARK 10 ------------------" << std::endl;
00288 #endif
00289         //Doit pouvoir réveiller le get ici (a vérifier)
00290         expectedDataReceived = true;
00291       }
00292     }
00293    
00294     if (expectedDataReceived) {
00295 #ifdef MYDEBUG
00296       std::cout << "-------- Put : MARK 11 ------------------" << std::endl;
00297 #endif
00298       // si waitingForAnyDataId était positionné, c'est forcément lui qui a activer
00299       // expectedDataReceived à true
00300       if (waitingForAnyDataId) 
00301         waitingForAnyDataId        = false;
00302       else 
00303         waitingForConvenientDataId = false;
00304       // Reveille le thread du destinataire (stoppe son attente)
00305       // Ne faudrait-il pas réveiller plutôt tous les threads ?
00306       // Celui  réveillé ne correspond pas forcément à celui qui demande
00307       // cet expectedDataReceived.
00308       // Pb1 : cas d'un un get séquentiel et d'un get sur un dataId que l'on vient de recevoir.
00309       // Si l'on reveille le mauvais thread, l'autre va attendre indéfiniment ! (sauf timeout)
00310       // Pb2 : également si deux attentes de DataIds même différents car on n'en stocke qu'un !
00311       // Conclusion : Pour l'instant on ne gère pas un service multithreadé qui effectue
00312       // des lectures simultanées sur le même port !
00313 #ifdef MYDEBUG
00314       std::cerr << "-------- Put : new datas available ------------------" << std::endl;
00315 #endif
00316       fflush(stdout);fflush(stderr);
00317       cond_instance.signal();
00318     }
00319 #ifdef MYDEBUG
00320     std::cout << "-------- Put : MARK 12 ------------------" << std::endl;
00321 #endif
00322 
00323     // Deverouille l'acces a la table : On peut remonter l'appel au dessus de expected...
00324     storedDatas_mutex.unlock();
00325 
00326 #ifdef MYDEBUG
00327     std::cout << "-------- Put : MARK 13 ------------------" << std::endl;
00328 #endif
00329     fflush(stdout);
00330     fflush(stderr);
00331 
00332   } // Catch les exceptions SALOME//C++ pour la transformer en une exception SALOME//CORBA  
00333   catch ( const SALOME_Exception & ex ) {
00334     // On évite de laisser un  mutex
00335     storedDatas_mutex.unlock();
00336     THROW_SALOME_CORBA_EXCEPTION(ex.what(), SALOME::INTERNAL_ERROR);
00337   }
00338 
00339 }
00340 
00341 
00342 // Version du Get en 0 copy
00343 // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas )
00344 // ( L'utilisateur devra être attentif à la politique de gestion de l'historique
00345 //   spécifique au mode de couplage car il peut y avoir une suppression potentielle 
00346 //   d'une donnée utilisée directement dans le code utilisateur )
00347 //  Le code doit prendre connaissance du transfert de propriété ou non des données
00348 //  auprès du mode de couplage choisi. 
00349 template < typename DataManipulator, typename COUPLING_POLICY >
00350 template < typename TimeType,typename TagType>
00351 typename DataManipulator::Type 
00352 GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType time, 
00353                                                    TagType  tag)
00354 // REM : Laisse passer toutes les exceptions
00355 //       En particulier les SALOME_Exceptions qui viennent de la COUPLING_POLICY
00356 //       Pour déclarer le throw avec l'exception spécifique il faut que je vérifie
00357 //       qu'un setunexpeted est positionné sinon le C++ arrête tout par appel à terminate
00358 {
00359   typedef typename COUPLING_POLICY::DataId DataId;
00360   // (Pointeur sur séquence) ou valeur..
00361   DataType dataToTransmit ;
00362   bool     isEqual, isBounded;
00363   typedef typename DataManipulator::InnerType InnerType;
00364 
00365 #ifdef MYDEBUG
00366   std::cout << "-------- Get : MARK 1 ------------------" << std::endl;
00367 #endif
00368   expectedDataId   = DataId(time,tag);
00369 #ifdef MYDEBUG
00370   std::cout << "-------- Get : MARK 2 ------------------" << std::endl;
00371 #endif
00372  
00373   typename DataTable::iterator wDataIt1;
00374 
00375   try {
00376     storedDatas_mutex.lock(); // Gérer les Exceptions ds le corps de la méthode
00377   
00378     while ( true ) {
00379  
00380       // Renvoie isEqual si le dataId attendu est trouvé dans storedDatas :
00381       //   - l'itérateur wDataIt1 pointe alors sur ce dataId
00382       // Renvoie isBounded si le dataId attendu n'est pas trouvé mais encadrable et 
00383       // que la politique  gére ce cas de figure 
00384       //   - l'itérateur wDataIt1 est tel que wDataIt1->first < wdataId < (wDataIt1+1)->first
00385       // Méthode provenant de la COUPLING_POLICY
00386       isDataIdConveniant(storedDatas,expectedDataId,isEqual,isBounded,wDataIt1);
00387 #ifdef MYDEBUG
00388       std::cout << "-------- Get : MARK 3 ------------------" << std::endl;
00389 #endif
00390 
00391       // L'ordre des différents tests est important
00392       if ( isEqual ) {
00393  
00394 #ifdef MYDEBUG
00395         std::cout << "-------- Get : MARK 4 ------------------" << std::endl;
00396 #endif
00397         // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM.
00398         // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
00399         // C'est EraseDataId qui choisi ou non de supprimer la donnée
00400         // Du coup interaction potentielle entre le 0 copy et gestion de l'historique
00401         dataToTransmit = (*wDataIt1).second; 
00402 
00403 #ifdef MYDEBUG
00404         std::cout << "-------- Get : MARK 5 ------------------" << std::endl;
00405         std::cout << "-------- Get : Données trouvées à t : " << std::endl;
00406         typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit);
00407         size_t   N = DataManipulator::size(dataToTransmit);
00408         std::copy(InIt1,        InIt1 + N,
00409                   std::ostream_iterator< InnerType > (std::cout," "));
00410         std::cout << std::endl;
00411 #endif
00412 
00413         // Décide de la suppression de certaines  instances de données 
00414         // La donnée contenu dans la structure CORBA et son dataId sont désallouées
00415         // Méthode provenant de la COUPLING_POLICY 
00416         typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
00417         processEraseDataId.apply(storedDatas,wDataIt1);
00418 #ifdef MYDEBUG
00419         std::cout << "-------- Get : MARK 6 ------------------" << std::endl;
00420 #endif
00421         break;
00422 
00423       }
00424 #ifdef MYDEBUG
00425       std::cout << "-------- Get : MARK 7 ------------------" << std::endl;
00426 #endif
00427 
00428       //if (  isBounded() && COUPLING_POLICY::template needToProcessBoundedDataId() ) {
00429       // Le DataId demandé n'est pas trouvé mais est encadré ET la politique de couplage
00430       // implémente une méthode processBoundedDataId capable de générer les données à retourner
00431       if (  isBounded ) {
00432         // Pour être cohérent avec la politique du bloc précédent
00433         // on stocke la paire (dataId,données interpolées ).
00434         // CALCIUM ne stockait pas les données interpolées. 
00435         // Cependant  comme les données sont censées être produites
00436         // par ordre croissant de DataId, de nouvelles données ne devrait pas améliorer
00437         // l'interpolation.
00438 #ifdef MYDEBUG
00439         std::cout << "-------- Get : MARK 8 ------------------" << std::endl;
00440 #endif
00441 
00442         typedef typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> BDI;
00443         BDI processBoundedDataId(*this);
00444         //        typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> processBoundedDataId(*this);
00445         //si static BDIP::apply(dataToTransmit,expectedDataId,wDataIt1);
00446         //ancienne version template processBoundedDataId<DataManipulator>(dataToTransmit,expectedDataId,wDataIt1);
00447         //BDIP processBoundedDataId;
00448         processBoundedDataId.apply(dataToTransmit,expectedDataId,wDataIt1);
00449   
00450         // Il ne peut pas y avoir déjà une clé expectedDataId dans storedDatas (utilisation de la notation [] )
00451         // La nouvelle donnée produite est stockée, ce n'était pas le cas dans CALCIUM
00452         // Cette opération n'a peut être pas un caractère générique.
00453         // A déplacer en paramètre de la méthode précédente ? ou déléguer ce choix au mode de couplage ?
00454         storedDatas[expectedDataId]=dataToTransmit;
00455 
00456 #ifdef MYDEBUG
00457         std::cout << "-------- Get : Données calculées à t : " << std::endl;
00458         typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit);
00459         size_t   N = DataManipulator::size(dataToTransmit);
00460  
00461         std::copy(InIt1,        InIt1 + N,
00462                   std::ostream_iterator< InnerType > (std::cout," "));
00463         std::cout << std::endl;
00464         std::cout << "-------- Get : MARK 9 ------------------" << std::endl;
00465 #endif
00466 
00467         typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
00468         processEraseDataId.apply(storedDatas,wDataIt1);
00469    
00470         break;
00471       }
00472   
00473       // Délègue au mode de couplage la gestion d'une demande de donnée non disponible 
00474       // si le port est deconnecté
00475       typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this);
00476       if ( processDisconnect.apply(storedDatas, expectedDataId, wDataIt1) ) continue;
00477     
00478       // Réception bloquante sur le dataId demandé
00479       // Si l'instance de donnée n'est pas trouvee
00480 #ifdef MYDEBUG
00481       std::cout << "-------- Get : MARK 10 ------------------" << std::endl;
00482 #endif
00483       //Positionné à faux dans la méthode put
00484       waitingForConvenientDataId = true; 
00485 #ifdef MYDEBUG
00486       std::cout << "-------- Get : MARK 11 ------------------" << std::endl;
00487      
00488       // Ici on attend que la méthode put recoive la donnée 
00489       std::cout << "-------- Get : waiting datas ------------------" << std::endl;
00490 #endif
00491       fflush(stdout);fflush(stderr);
00492       unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut;
00493       if(rs==0)
00494         cond_instance.wait();
00495       else
00496         {
00497           //Timed wait on omni condition
00498           omni_thread::get_time(&ts,&tns, rs,0);
00499           int success=cond_instance.timedwait(ts,tns);
00500           if(!success)
00501             {
00502               // Waiting too long probably blocking
00503               std::stringstream msg;
00504               msg<<"Timeout ("<<rs<<" s) exceeded";
00505               Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str());
00506               throw DSC_Exception(msg.str());
00507             }
00508         }
00509 
00510 
00511 #ifdef MYDEBUG
00512       std::cout << "-------- Get : MARK 12 ------------------" << std::endl;
00513 #endif
00514     }
00515 
00516   } catch (...) {
00517     waitingForConvenientDataId = true;
00518     storedDatas_mutex.unlock();
00519     throw;
00520   }
00521 
00522   // Deverouille l'acces a la table
00523   storedDatas_mutex.unlock();
00524 #ifdef MYDEBUG
00525   std::cout << "-------- Get : MARK 13 ------------------" << std::endl;
00526 #endif
00527 
00528   // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM
00529   // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
00530   // c'est eraseDataId qui choisi ou non de supprimer la donnée
00531   // Du coup interaction potentielle entre le 0 copy et gestion des niveaux 
00532   return dataToTransmit; 
00533 
00534 }
00535 
00536 template < typename DataManipulator, typename COUPLING_POLICY >
00537 template < typename TimeType,typename TagType>
00538 typename DataManipulator::Type 
00539 GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType& ti,
00540                                                    TimeType tf, 
00541                                                    TagType  tag ) {
00542   ti = COUPLING_POLICY::getEffectiveTime(ti,tf);
00543   return get(ti,tag);
00544 }
00545 
00546 
00547 // Version du next en 0 copy
00548 // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas )
00549 template < typename DataManipulator, typename COUPLING_POLICY >
00550 template < typename TimeType,typename TagType>
00551 typename DataManipulator::Type 
00552 GenericPort<DataManipulator, COUPLING_POLICY>::next(TimeType &t,
00553                                                     TagType  &tag ) {
00554  
00555   typedef  typename COUPLING_POLICY::DataId DataId;
00556 
00557   DataType dataToTransmit;
00558   DataId   dataId;
00559 
00560   try {
00561     storedDatas_mutex.lock();// Gérer les Exceptions ds le corps de la méthode
00562 
00563 #ifdef MYDEBUG
00564     std::cout << "-------- Next : MARK 1 ---lastDataIdSet ("<<lastDataIdSet<<")---------------" << std::endl;
00565 #endif
00566 
00567     typename DataTable::iterator wDataIt1;
00568     wDataIt1 = storedDatas.end();
00569 
00570     //Recherche le prochain dataId à renvoyer
00571     // - lastDataIdset == true indique que lastDataId
00572     // contient le dernier DataId renvoyé
00573     // - lastDataIdset == false indique que l'on renverra
00574     //   le premier dataId trouvé
00575     // - upper_bound(lastDataId) situe le prochain DataId
00576     // à renvoyer
00577     // Rem : les données renvoyées ne sont effacées par eraseDataIds
00578     //       si necessaire
00579     if (lastDataIdSet) 
00580       wDataIt1 = storedDatas.upper_bound(lastDataId);
00581     else if ( !storedDatas.empty() ) {
00582       lastDataIdSet = true;
00583       wDataIt1      = storedDatas.begin();
00584     }
00585 
00586     typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this);
00587 
00588     while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) {
00589 
00590       // Délègue au mode de couplage la gestion d'une demande de donnée non disponible 
00591       // si le port est deconnecté
00592       if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) )  {
00593         waitingForAnyDataId = false; break;
00594       }
00595   
00596 #ifdef MYDEBUG
00597       std::cout << "-------- Next : MARK 2 ------------------" << std::endl;
00598 #endif
00599       //Positionné à faux dans la méthode put
00600       waitingForAnyDataId   = true;
00601 #ifdef MYDEBUG
00602       std::cout << "-------- Next : MARK 3 ------------------" << std::endl;
00603       // Ici on attend que la méthode put recoive la donnée 
00604       std::cout << "-------- Next : waiting datas ------------------" << std::endl;
00605 #endif
00606       fflush(stdout);fflush(stderr);
00607       unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut;
00608       if(rs==0)
00609         cond_instance.wait();
00610       else
00611         {
00612           //Timed wait on omni condition
00613           omni_thread::get_time(&ts,&tns, rs,0);
00614           int success=cond_instance.timedwait(ts,tns);
00615           if(!success)
00616             {
00617               // Waiting too long probably blocking
00618               std::stringstream msg;
00619               msg<<"Timeout ("<<rs<<" s) exceeded";
00620               Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str());
00621               throw DSC_Exception(msg.str());
00622             }
00623         }
00624 
00625       if (lastDataIdSet) {
00626 #ifdef MYDEBUG
00627         std::cout << "-------- Next : MARK 4 ------------------" << std::endl;
00628 #endif
00629         wDataIt1 = storedDatas.upper_bound(lastDataId);
00630       } else  {
00631 #ifdef MYDEBUG
00632         std::cout << "-------- Next : MARK 5 ------------------" << std::endl;
00633 #endif
00634         lastDataIdSet = true;
00635         wDataIt1      = storedDatas.begin();
00636       }
00637     }
00638 
00639 #ifdef MYDEBUG
00640     std::cout << "-------- Next : MARK 6 ------------------" << std::endl;
00641 #endif
00642 
00643     t   = getTime( (*wDataIt1).first );
00644     tag = getTag ( (*wDataIt1).first );
00645     dataToTransmit = (*wDataIt1).second;
00646  
00647 #ifdef MYDEBUG
00648     std::cout << "-------- Next : MARK 7 ------------------" << std::endl;
00649 #endif
00650     lastDataId    = (*wDataIt1).first;
00651 
00652     typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
00653     processEraseDataId.apply(storedDatas, wDataIt1);
00654 
00655 #ifdef MYDEBUG
00656     std::cout << "-------- Next : MARK 8 ------------------" << std::endl;   
00657 #endif
00658   } catch (...) {
00659 #ifdef MYDEBUG
00660     std::cout << "-------- Next : MARK 8bis ------------------" << std::endl;
00661 #endif
00662     waitingForAnyDataId = false;
00663     storedDatas_mutex.unlock();
00664     throw;
00665   }
00666   storedDatas_mutex.unlock();
00667   
00668 #ifdef MYDEBUG
00669   std::cout << "-------- Next : MARK 9 ------------------" << std::endl;
00670 #endif
00671 
00672   // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM
00673   // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
00674   // c'est eraseDataId qui choisi ou non de supprimer la donnée
00675   // Du coup interaction potentielle entre le 0 copy et gestion des niveaux 
00676   return dataToTransmit; 
00677 
00678 };
00679 
00680 #endif