1 // Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : GenericPort.hxx
24 // Author : Eric Fayolle (EDF)
26 // Modified by : $LastChangedBy$
27 // Date : $LastChangedDate: 2007-02-28 15:26:32 +0100 (mer, 28 fév 2007) $
30 #ifndef _GENERIC_PORT_HXX_
31 #define _GENERIC_PORT_HXX_
33 #include "CorbaTypeManipulator.hxx"
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"
46 // Inclusions pour l'affichage
53 // --------------------------------
55 // Definition: Implemente un port de type "data-stream"
56 // Cette implémentation gère tous les types de données définies par DataManipulator::type
57 // Ce port est soumis à une politique d'itération sur les identificateurs de données (DataId)
58 // Un identificateur de données est construit à partir d'un ou plusieurs paramètres de la méthode put
59 // tels que : une date, une itération, un pas de temps ou une combinaison de ces paramètres.
61 template < typename DataManipulator, class COUPLING_POLICY >
62 class GenericPort : public COUPLING_POLICY {
64 // Type de données manipulés
65 typedef typename DataManipulator::Type DataType;
66 typedef typename DataManipulator::CorbaInType CorbaInDataType;
69 virtual ~GenericPort();
71 template <typename TimeType,typename TagType> void put(CorbaInDataType data, TimeType time, TagType tag);
72 template <typename TimeType,typename TagType> DataType get(TimeType time, TagType tag);
73 template <typename TimeType,typename TagType> DataType get(TimeType& ti, TimeType tf, TagType tag = 0);
74 template <typename TimeType,typename TagType> DataType next(TimeType &t, TagType &tag );
75 void close (PortableServer::POA_var poa, PortableServer::ObjectId_var id);
77 template <typename TimeType,typename TagType> void erase(TimeType time, TagType tag, bool before );
81 // Type identifiant une instance de donnee. Exemple (time,tag)
82 typedef typename COUPLING_POLICY::DataId DataId;
83 typedef std::map< DataId, DataType> DataTable;
85 // Stockage des donnees recues et non encore distribuées
86 DataTable storedDatas ;
88 // Indicateur que le destinataire attend une instance particuliere de données
89 bool waitingForConvenientDataId;
90 // Indicateur que le destinataire attend n'importe qu'elle instance de données
91 bool waitingForAnyDataId;
93 // Identificateur de la donné que le destinataire (propriétaire du port) attend
94 DataId expectedDataId ;
95 // Sauvegarde du DataId courant pour la méthode next
98 // Exclusion mutuelle d'acces a la table des données reçues
99 omni_mutex storedDatas_mutex;
100 // Condition d'attente d'une instance (Le processus du Get attend la condition declaree par le processus Put)
101 omni_condition cond_instance;
105 template < typename DataManipulator, typename COUPLING_POLICY >
106 GenericPort<DataManipulator, COUPLING_POLICY >::GenericPort() :
107 cond_instance(& this->storedDatas_mutex),waitingForConvenientDataId(false),
108 waitingForAnyDataId(false),lastDataIdSet(false) {}
110 template < typename DataManipulator, typename COUPLING_POLICY>
111 GenericPort<DataManipulator, COUPLING_POLICY>::~GenericPort() {
112 typename DataTable::iterator it;
113 for (it=storedDatas.begin(); it!=storedDatas.end(); ++it) {
115 std::cerr << "~GenericPort() : destruction de la donnnée associée au DataId :"<< (*it).first << std::endl;
117 DataManipulator::delete_data( (*it).second );
121 template < typename DataManipulator, typename COUPLING_POLICY> void
122 GenericPort<DataManipulator, COUPLING_POLICY>::close (PortableServer::POA_var poa,
123 PortableServer::ObjectId_var id) {
124 // Ferme le port en supprimant le servant
125 // La desactivation du servant du POA provoque sa suppression
126 poa->deactivate_object (id);
129 template < typename DataManipulator, typename COUPLING_POLICY> void
130 GenericPort<DataManipulator, COUPLING_POLICY>::wakeupWaiting()
133 std::cout << "-------- wakeupWaiting ------------------" << std::endl;
135 storedDatas_mutex.lock();
136 if (waitingForAnyDataId || waitingForConvenientDataId) {
138 std::cout << "-------- wakeupWaiting:signal --------" << std::endl;
139 std::cout << std::flush;
141 cond_instance.signal();
143 storedDatas_mutex.unlock();
147 /* Methode put_generique
149 * Stocke en memoire une instance de donnee (pointeur) que l'emetteur donne a l'intention du destinataire.
150 * Reveille le destinataire, si il y a lieu.
152 template < typename DataManipulator, typename COUPLING_POLICY>
153 template < typename TimeType,typename TagType>
154 void GenericPort<DataManipulator, COUPLING_POLICY>::put(CorbaInDataType dataParam,
161 // Affichage des donnees pour DEBUGging
162 std::cerr << "parametres emis: " << time << ", " << tag << std::endl;
163 DataManipulator::dump(dataParam);
166 // L'intérêt des paramètres time et tag pour ce port est décidé dans la politique de couplage
167 // Il est possible de filtrer en prenant en compte uniquement un paramètre time/tag ou les deux
168 // Il est également possible de convertir les données recues ou bien de les dupliquer
169 // pour plusieurs valeurs de time et/ou tag (d'où la notion de container dans la politique de couplage)
170 typedef typename COUPLING_POLICY::DataIdContainer DataIdContainer;
171 typedef typename COUPLING_POLICY::DataId DataId;
173 DataId dataId(time,tag);
174 // Effectue les traitements spécifiques à la politique de couplage
175 // pour construire une liste d'ids (par filtrage, conversion ...)
176 // DataIdContainer dataIds(dataId,*(static_cast<const COUPLING_POLICY *>(this)));
177 DataIdContainer dataIds(dataId, *this);
179 typename DataIdContainer::iterator dataIdIt = dataIds.begin();
181 bool expectedDataReceived = false;
184 std::cout << "-------- Put : MARK 1 ------------------" << std::endl;
186 if ( dataIds.empty() ) return;
188 std::cout << "-------- Put : MARK 1bis ------------------" << std::endl;
191 // Recupere les donnees venant de l'ORB et relâche les structures CORBA
192 // qui n'auraient plus cours en sortie de méthode put
193 DataType data = DataManipulator::get_data(dataParam);
199 std::cout << "-------- Put : MARK 2 ------ "<< (dataIdIt == dataIds.end()) << "------------" << std::endl;
200 std::cout << "-------- Put : MARK 2bis "<< (*dataIdIt) <<"------------------" << std::endl;
202 storedDatas_mutex.lock();
204 for (;dataIdIt != dataIds.end();++dataIdIt) {
207 std::cout << "-------- Put : MARK 3 ------------------" << std::endl;
209 // Duplique l'instance de donnée pour les autres dataIds
210 if (nbOfIter > 0) data = DataManipulator::clone(data);
212 std::cout << "-------- Put : MARK 3bis -----"<< dataIdIt.operator*() <<"------------" << std::endl;
215 DataId currentDataId=*dataIdIt;
218 std::cerr << "processing dataId : "<< currentDataId << std::endl;
220 std::cout << "-------- Put : MARK 4 ------------------" << std::endl;
223 // Ajoute l'instance de la donnee a sa place dans la table de données
224 // ou remplace une instance précédente si elle existe
226 // Recherche la première clé telle quelle ne soit pas < currentDataId
227 // pour celà l'opérateur de comparaison storedDatas.key_comp() est utilisé
228 // <=> premier emplacement où l'on pourrait insérer notre DataId
229 // <=> en général équivaux à (*wDataIt).first >= currentDataId
230 typename DataTable::iterator wDataIt = storedDatas.lower_bound(currentDataId);
232 std::cout << "-------- Put : MARK 5 ------------------" << std::endl;
235 // On n'a pas trouvé de dataId supérieur au notre ou
236 // on a trouvé une clé > à cet Id
237 if (wDataIt == storedDatas.end() || storedDatas.key_comp()(currentDataId,(*wDataIt).first) ) {
239 std::cout << "-------- Put : MARK 6 ------------------" << std::endl;
241 // Ajoute la donnee dans la table
242 wDataIt = storedDatas.insert(wDataIt, make_pair (currentDataId, data));
244 // Si on n'est pas en fin de liste et qu'il n'y a pas de relation d'ordre strict
245 // entre notre dataId et le DataId pointé c'est qu'ils sont identiques
247 std::cout << "-------- Put : MARK 7 ------------------" << std::endl;
249 // Les données sont remplacées par les nouvelles valeurs
250 // lorsque que le dataId existe déjà
251 DataType old_data = (*wDataIt).second;
252 (*wDataIt).second = data;
253 // Detruit la vieille donnee
254 DataManipulator::delete_data (old_data);
258 std::cout << "-------- Put : MARK 8 ------------------" << std::endl;
260 // Compte le nombre de dataIds à traiter
264 std::cout << "-------- Put : waitingForConvenientDataId : " << waitingForConvenientDataId <<"---" << std::endl;
265 std::cout << "-------- Put : waitingForAnyDataId : " << waitingForAnyDataId <<"---" << std::endl;
266 std::cout << "-------- Put : currentDataId : " << currentDataId <<"---" << std::endl;
267 std::cout << "-------- Put : expectedDataId : " << expectedDataId <<"---" << std::endl;
268 std::cout << "-------- Put : MARK 9 ------------------" << std::endl;
271 // A simplifier mais :
272 // - pas possible de mettre des arguments optionnels à cause
273 // du type itérator qui n'est pas connu (pas de possibilité de déclarer un static )
274 // - compliquer de créer une méthode sans les paramètres inutiles tout en réutilisant
275 // la méthode initiale car cette dernière ne peut pas être déclarée virtuelle
276 // à cause de ses paramètres templates. Du coup, il faudrait aussi redéfinir la
277 // méthode simplifiée dans les classes définissant une politique
278 // de couplage particulière ...
279 bool dummy1,dummy2; typename DataTable::iterator dummy3;
280 // Par construction, les valeurs de waitingForAnyDataId, waitingForConvenientDataId et de
281 // expectedDataId ne peuvent pas être modifiées pendant le traitement de la boucle
282 // sur les dataIds (à cause du lock utilisé dans la méthode put et les méthodes get )
283 // rem : Utilisation de l'évaluation gauche droite du logical C or
284 if ( waitingForAnyDataId ||
285 ( waitingForConvenientDataId &&
286 this->isDataIdConveniant(storedDatas, expectedDataId, dummy1, dummy2, dummy3) )
289 std::cout << "-------- Put : MARK 10 ------------------" << std::endl;
291 //Doit pouvoir réveiller le get ici (a vérifier)
292 expectedDataReceived = true;
296 if (expectedDataReceived) {
298 std::cout << "-------- Put : MARK 11 ------------------" << std::endl;
300 // si waitingForAnyDataId était positionné, c'est forcément lui qui a activer
301 // expectedDataReceived à true
302 if (waitingForAnyDataId)
303 waitingForAnyDataId = false;
305 waitingForConvenientDataId = false;
306 // Reveille le thread du destinataire (stoppe son attente)
307 // Ne faudrait-il pas réveiller plutôt tous les threads ?
308 // Celui réveillé ne correspond pas forcément à celui qui demande
309 // cet expectedDataReceived.
310 // Pb1 : cas d'un un get séquentiel et d'un get sur un dataId que l'on vient de recevoir.
311 // Si l'on reveille le mauvais thread, l'autre va attendre indéfiniment ! (sauf timeout)
312 // Pb2 : également si deux attentes de DataIds même différents car on n'en stocke qu'un !
313 // Conclusion : Pour l'instant on ne gère pas un service multithreadé qui effectue
314 // des lectures simultanées sur le même port !
316 std::cerr << "-------- Put : new datas available ------------------" << std::endl;
318 fflush(stdout);fflush(stderr);
319 cond_instance.signal();
322 std::cout << "-------- Put : MARK 12 ------------------" << std::endl;
325 // Deverouille l'acces a la table : On peut remonter l'appel au dessus de expected...
326 storedDatas_mutex.unlock();
329 std::cout << "-------- Put : MARK 13 ------------------" << std::endl;
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);
343 // erase data before time or tag
344 template < typename DataManipulator, typename COUPLING_POLICY >
345 template <typename TimeType,typename TagType>
347 GenericPort<DataManipulator, COUPLING_POLICY>::erase(TimeType time, TagType tag, bool before)
349 typename COUPLING_POLICY::template EraseDataIdBeforeOrAfterTagProcessor<DataManipulator> processEraseDataId(*this);
350 processEraseDataId.apply(storedDatas,time,tag,before);
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,
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
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;
377 std::cout << "-------- Get : MARK 1 ------------------" << std::endl;
379 expectedDataId = DataId(time,tag);
381 std::cout << "-------- Get : MARK 2 ------------------" << std::endl;
384 typename DataTable::iterator wDataIt1;
387 storedDatas_mutex.lock(); // Gérer les Exceptions ds le corps de la méthode
391 // Renvoie isEqual si le dataId attendu est trouvé dans storedDatas :
392 // - l'itérateur wDataIt1 pointe alors sur ce dataId
393 // Renvoie isBounded si le dataId attendu n'est pas trouvé mais encadrable et
394 // que la politique gére ce cas de figure
395 // - l'itérateur wDataIt1 est tel que wDataIt1->first < wdataId < (wDataIt1+1)->first
396 // Méthode provenant de la COUPLING_POLICY
397 this->isDataIdConveniant(storedDatas,expectedDataId,isEqual,isBounded,wDataIt1);
399 std::cout << "-------- Get : MARK 3 ------------------" << std::endl;
402 // L'ordre des différents tests est important
406 std::cout << "-------- Get : MARK 4 ------------------" << std::endl;
408 // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM.
409 // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
410 // C'est EraseDataId qui choisi ou non de supprimer la donnée
411 // Du coup interaction potentielle entre le 0 copy et gestion de l'historique
412 dataToTransmit = (*wDataIt1).second;
415 std::cout << "-------- Get : MARK 5 ------------------" << std::endl;
416 std::cout << "-------- Get : Données trouvées à t : " << std::endl;
417 typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit);
418 size_t N = DataManipulator::size(dataToTransmit);
419 std::copy(InIt1, InIt1 + N,
420 std::ostream_iterator< InnerType > (std::cout," "));
421 std::cout << std::endl;
424 // Décide de la suppression de certaines instances de données
425 // La donnée contenu dans la structure CORBA et son dataId sont désallouées
426 // Méthode provenant de la COUPLING_POLICY
427 typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
428 processEraseDataId.apply(storedDatas,wDataIt1);
430 std::cout << "-------- Get : MARK 6 ------------------" << std::endl;
436 std::cout << "-------- Get : MARK 7 ------------------" << std::endl;
439 //if ( isBounded() && COUPLING_POLICY::template needToProcessBoundedDataId() ) {
440 // Le DataId demandé n'est pas trouvé mais est encadré ET la politique de couplage
441 // implémente une méthode processBoundedDataId capable de générer les données à retourner
443 // Pour être cohérent avec la politique du bloc précédent
444 // on stocke la paire (dataId,données interpolées ).
445 // CALCIUM ne stockait pas les données interpolées.
446 // Cependant comme les données sont censées être produites
447 // par ordre croissant de DataId, de nouvelles données ne devrait pas améliorer
450 std::cout << "-------- Get : MARK 8 ------------------" << std::endl;
453 typedef typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> BDI;
454 BDI processBoundedDataId(*this);
455 // typename COUPLING_POLICY::template BoundedDataIdProcessor<DataManipulator> processBoundedDataId(*this);
456 //si static BDIP::apply(dataToTransmit,expectedDataId,wDataIt1);
457 //ancienne version template processBoundedDataId<DataManipulator>(dataToTransmit,expectedDataId,wDataIt1);
458 //BDIP processBoundedDataId;
459 processBoundedDataId.apply(dataToTransmit,expectedDataId,wDataIt1);
461 // Il ne peut pas y avoir déjà une clé expectedDataId dans storedDatas (utilisation de la notation [] )
462 // La nouvelle donnée produite est stockée, ce n'était pas le cas dans CALCIUM
463 // Cette opération n'a peut être pas un caractère générique.
464 // A déplacer en paramètre de la méthode précédente ? ou déléguer ce choix au mode de couplage ?
465 storedDatas[expectedDataId]=dataToTransmit;
468 std::cout << "-------- Get : Données calculées à t : " << std::endl;
469 typename DataManipulator::InnerType const * const InIt1 = DataManipulator::getPointer(dataToTransmit);
470 size_t N = DataManipulator::size(dataToTransmit);
472 std::copy(InIt1, InIt1 + N,
473 std::ostream_iterator< InnerType > (std::cout," "));
474 std::cout << std::endl;
475 std::cout << "-------- Get : MARK 9 ------------------" << std::endl;
478 typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
479 processEraseDataId.apply(storedDatas,wDataIt1);
484 // Délègue au mode de couplage la gestion d'une demande de donnée non disponible
485 // si le port est deconnecté
486 typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this);
487 if ( processDisconnect.apply(storedDatas, expectedDataId, wDataIt1) ) continue;
489 // Réception bloquante sur le dataId demandé
490 // Si l'instance de donnée n'est pas trouvee
492 std::cout << "-------- Get : MARK 10 ------------------" << std::endl;
494 //Positionné à faux dans la méthode put
495 waitingForConvenientDataId = true;
497 std::cout << "-------- Get : MARK 11 ------------------" << std::endl;
499 // Ici on attend que la méthode put recoive la donnée
500 std::cout << "-------- Get : waiting datas ------------------" << std::endl;
502 fflush(stdout);fflush(stderr);
503 unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut;
505 cond_instance.wait();
508 //Timed wait on omni condition
509 omni_thread::get_time(&ts,&tns, rs,0);
510 int success=cond_instance.timedwait(ts,tns);
513 // Waiting too long probably blocking
514 std::stringstream msg;
515 msg<<"Timeout ("<<rs<<" s) exceeded";
516 Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str());
517 throw DSC_Exception(msg.str());
523 std::cout << "-------- Get : MARK 12 ------------------" << std::endl;
528 waitingForConvenientDataId = true;
529 storedDatas_mutex.unlock();
533 // Deverouille l'acces a la table
534 storedDatas_mutex.unlock();
536 std::cout << "-------- Get : MARK 13 ------------------" << std::endl;
539 // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM
540 // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
541 // c'est eraseDataId qui choisi ou non de supprimer la donnée
542 // Du coup interaction potentielle entre le 0 copy et gestion des niveaux
543 return dataToTransmit;
547 template < typename DataManipulator, typename COUPLING_POLICY >
548 template < typename TimeType,typename TagType>
549 typename DataManipulator::Type
550 GenericPort<DataManipulator, COUPLING_POLICY>::get(TimeType& ti,
553 ti = COUPLING_POLICY::getEffectiveTime(ti,tf);
558 // Version du next en 0 copy
559 // ( n'effectue pas de recopie de la donnée trouvée dans storedDatas )
560 template < typename DataManipulator, typename COUPLING_POLICY >
561 template < typename TimeType,typename TagType>
562 typename DataManipulator::Type
563 GenericPort<DataManipulator, COUPLING_POLICY>::next(TimeType &t,
566 typedef typename COUPLING_POLICY::DataId DataId;
568 DataType dataToTransmit;
572 storedDatas_mutex.lock();// Gérer les Exceptions ds le corps de la méthode
575 std::cout << "-------- Next : MARK 1 ---lastDataIdSet ("<<lastDataIdSet<<")---------------" << std::endl;
578 typename DataTable::iterator wDataIt1;
579 wDataIt1 = storedDatas.end();
581 //Recherche le prochain dataId à renvoyer
582 // - lastDataIdset == true indique que lastDataId
583 // contient le dernier DataId renvoyé
584 // - lastDataIdset == false indique que l'on renverra
585 // le premier dataId trouvé
586 // - upper_bound(lastDataId) situe le prochain DataId
588 // Rem : les données renvoyées ne sont effacées par eraseDataIds
591 wDataIt1 = storedDatas.upper_bound(lastDataId);
592 else if ( !storedDatas.empty() ) {
593 lastDataIdSet = true;
594 wDataIt1 = storedDatas.begin();
597 typename COUPLING_POLICY::template DisconnectProcessor<DataManipulator> processDisconnect(*this);
599 while ( storedDatas.empty() || wDataIt1 == storedDatas.end() ) {
601 // Délègue au mode de couplage la gestion d'une demande de donnée non disponible
602 // si le port est deconnecté
603 if ( processDisconnect.apply(storedDatas, lastDataId, wDataIt1) ) {
604 waitingForAnyDataId = false; break;
608 std::cout << "-------- Next : MARK 2 ------------------" << std::endl;
610 //Positionné à faux dans la méthode put
611 waitingForAnyDataId = true;
613 std::cout << "-------- Next : MARK 3 ------------------" << std::endl;
614 // Ici on attend que la méthode put recoive la donnée
615 std::cout << "-------- Next : waiting datas ------------------" << std::endl;
617 fflush(stdout);fflush(stderr);
618 unsigned long ts, tns,rs=Superv_Component_i::dscTimeOut;
620 cond_instance.wait();
623 //Timed wait on omni condition
624 omni_thread::get_time(&ts,&tns, rs,0);
625 int success=cond_instance.timedwait(ts,tns);
628 // Waiting too long probably blocking
629 std::stringstream msg;
630 msg<<"Timeout ("<<rs<<" s) exceeded";
631 Engines_DSC_interface::writeEvent("BLOCKING","","","","Probably blocking",msg.str().c_str());
632 throw DSC_Exception(msg.str());
638 std::cout << "-------- Next : MARK 4 ------------------" << std::endl;
640 wDataIt1 = storedDatas.upper_bound(lastDataId);
643 std::cout << "-------- Next : MARK 5 ------------------" << std::endl;
645 lastDataIdSet = true;
646 wDataIt1 = storedDatas.begin();
651 std::cout << "-------- Next : MARK 6 ------------------" << std::endl;
654 t = this->getTime( (*wDataIt1).first );
655 tag = this->getTag ( (*wDataIt1).first );
656 dataToTransmit = (*wDataIt1).second;
659 std::cout << "-------- Next : MARK 7 ------------------" << std::endl;
661 lastDataId = (*wDataIt1).first;
663 typename COUPLING_POLICY::template EraseDataIdProcessor<DataManipulator> processEraseDataId(*this);
664 processEraseDataId.apply(storedDatas, wDataIt1);
667 std::cout << "-------- Next : MARK 8 ------------------" << std::endl;
671 std::cout << "-------- Next : MARK 8bis ------------------" << std::endl;
673 waitingForAnyDataId = false;
674 storedDatas_mutex.unlock();
677 storedDatas_mutex.unlock();
680 std::cout << "-------- Next : MARK 9 ------------------" << std::endl;
683 // La propriété de la données N'EST PAS transmise à l'utilisateur en mode CALCIUM
684 // Si l'utilisateur supprime la donnée, storedDataIds devient incohérent
685 // c'est eraseDataId qui choisi ou non de supprimer la donnée
686 // Du coup interaction potentielle entre le 0 copy et gestion des niveaux
687 return dataToTransmit;