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