Salome HOME
9a94da2d73493a962f1ac3d3d3510694c85c9c3f
[modules/kernel.git] / src / DSC / DSC_User / Datastream / GenericPort.hxx
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
39 #include "Utils_SALOME_Exception.hxx"
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
67   GenericPort(); 
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
85   DataTable storedDatas ;
86
87   // Indicateur que le destinataire attend une instance particuliere de données
88   bool     waitingForConvenientDataId;
89   // Indicateur que le destinataire attend n'importe qu'elle instance de données
90   bool     waitingForAnyDataId;
91
92   // Identificateur de la donné que le destinataire (propriétaire du port) attend
93   DataId   expectedDataId ;
94   // Sauvegarde du DataId courant pour la méthode next 
95   DataId   lastDataId;
96   bool     lastDataIdSet;
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 >
105 GenericPort<DataManipulator, COUPLING_POLICY >::GenericPort() :
106   waitingForConvenientDataId(false),waitingForAnyDataId(false),lastDataIdSet(false),
107   cond_instance(& this->storedDatas_mutex){}
108
109 template < typename DataManipulator, typename COUPLING_POLICY>
110 GenericPort<DataManipulator, COUPLING_POLICY>::~GenericPort() {
111   typename DataTable::iterator it;
112   for (it=storedDatas.begin(); it!=storedDatas.end(); ++it) {
113     if (SALOME::VerbosityActivated())
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 
121 GenericPort<DataManipulator, COUPLING_POLICY>::close (PortableServer::POA_var poa, 
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
129 GenericPort<DataManipulator, COUPLING_POLICY>::wakeupWaiting()
130 {
131   if (SALOME::VerbosityActivated())
132     std::cout << "-------- wakeupWaiting ------------------" << std::endl;
133
134   storedDatas_mutex.lock();
135   if (waitingForAnyDataId || waitingForConvenientDataId) {
136     if (SALOME::VerbosityActivated())
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>
155 void GenericPort<DataManipulator, COUPLING_POLICY>::put(CorbaInDataType dataParam, 
156                                                         TimeType time, 
157                                                         TagType  tag) {
158   fflush(stdout);
159   fflush(stderr);
160   try {
161     if (SALOME::VerbosityActivated())
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
185     if (SALOME::VerbosityActivated())
186       std::cout << "-------- Put : MARK 1 ------------------" << std::endl;
187
188     if ( dataIds.empty() ) return;
189     if (SALOME::VerbosityActivated())
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
198     if (SALOME::VerbosityActivated())
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) {
206       if (SALOME::VerbosityActivated())
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);
211       if (SALOME::VerbosityActivated())
212         std::cout << "-------- Put : MARK 3bis -----"<< dataIdIt.operator*() <<"------------" << std::endl;
213     
214       DataId currentDataId=*dataIdIt;
215
216     if (SALOME::VerbosityActivated())
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é
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);
230       if (SALOME::VerbosityActivated())
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) ) {
236         if (SALOME::VerbosityActivated())
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
244         if (SALOME::VerbosityActivated())
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à
249         DataType old_data = (*wDataIt).second;
250         (*wDataIt).second = data;
251         // Detruit la vieille donnee
252         DataManipulator::delete_data (old_data);
253       }
254   
255       if (SALOME::VerbosityActivated())
256         std::cout << "-------- Put : MARK 8 ------------------" << std::endl;
257
258       // Compte le nombre de dataIds à traiter
259       ++nbOfIter;
260
261       if (SALOME::VerbosityActivated())
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       {
288         if (SALOME::VerbosityActivated())
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) {
297       if (SALOME::VerbosityActivated())
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 !
315       if (SALOME::VerbosityActivated())
316         std::cerr << "-------- Put : new datas available ------------------" << std::endl;
317
318       fflush(stdout);fflush(stderr);
319       cond_instance.signal();
320     }
321
322     if (SALOME::VerbosityActivated())
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
328     if (SALOME::VerbosityActivated())
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();
338     THROW_SALOME_CORBA_EXCEPTION(ex.what(), SALOME::INTERNAL_ERROR);
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
347 GenericPort<DataManipulator, COUPLING_POLICY>::erase(TimeType time, TagType  tag, bool before)
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 
363 GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType time, 
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
376   if (SALOME::VerbosityActivated())
377     std::cout << "-------- Get : MARK 1 ------------------" << std::endl;
378
379   expectedDataId   = DataId(time,tag);
380   if (SALOME::VerbosityActivated())
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);
397       if (SALOME::VerbosityActivated())
398         std::cout << "-------- Get : MARK 3 ------------------" << std::endl;
399
400       // L'ordre des différents tests est important
401       if ( isEqual ) {
402         if (SALOME::VerbosityActivated())
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
411         if (SALOME::VerbosityActivated())
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);
427         if (SALOME::VerbosityActivated())
428           std::cout << "-------- Get : MARK 6 ------------------" << std::endl;
429
430         break;
431       }
432
433       if (SALOME::VerbosityActivated())
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.
446       if (SALOME::VerbosityActivated())
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
463         if (SALOME::VerbosityActivated())
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é
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é
487       // Si l'instance de donnée n'est pas trouvee
488       if (SALOME::VerbosityActivated())
489         std::cout << "-------- Get : MARK 10 ------------------" << std::endl;
490
491       //Positionné à faux dans la méthode put
492       waitingForConvenientDataId = true; 
493       if (SALOME::VerbosityActivated())
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
520       if (SALOME::VerbosityActivated())
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();
531   if (SALOME::VerbosityActivated())
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 
545 GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType& ti,
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 
558 GenericPort<DataManipulator, COUPLING_POLICY>::next(TimeType &t,
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
569     if (SALOME::VerbosityActivated())
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é
578     // - lastDataIdset == false indique que l'on renverra
579     //   le premier dataId trouvé
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é
597       if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) )  {
598         waitingForAnyDataId = false; break;
599       }
600   
601       if (SALOME::VerbosityActivated())
602         std::cout << "-------- Next : MARK 2 ------------------" << std::endl;
603
604       //Positionné à faux dans la méthode put
605       waitingForAnyDataId   = true;
606
607       if (SALOME::VerbosityActivated())
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) {
634         if (SALOME::VerbosityActivated())
635           std::cout << "-------- Next : MARK 4 ------------------" << std::endl;
636
637         wDataIt1 = storedDatas.upper_bound(lastDataId);
638       } else  {
639         if (SALOME::VerbosityActivated())
640           std::cout << "-------- Next : MARK 5 ------------------" << std::endl;
641
642         lastDataIdSet = true;
643         wDataIt1      = storedDatas.begin();
644       }
645     }
646
647     if (SALOME::VerbosityActivated())
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  
654     if (SALOME::VerbosityActivated())
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
662     if (SALOME::VerbosityActivated())
663       std::cout << "-------- Next : MARK 8 ------------------" << std::endl;   
664   } catch (...) {
665     if (SALOME::VerbosityActivated())
666       std::cout << "-------- Next : MARK 8bis ------------------" << std::endl;
667
668     waitingForAnyDataId = false;
669     storedDatas_mutex.unlock();
670     throw;
671   }
672   storedDatas_mutex.unlock();
673   
674   if (SALOME::VerbosityActivated())
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