SALOME documentation central

src/DSC/DSC_User/Datastream/Calcium/Copy2UserSpace.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   : Copy2UserSpace.hxx
00023 //  Author : Eric Fayolle (EDF)
00024 //  Module : KERNEL
00025 // Modified by : $LastChangedBy$
00026 // Date        : $LastChangedDate: 2007-02-13 11:09:09 +0100 (mar, 13 fév 2007) $
00027 // Id          : $Id$
00028 //
00029 #ifndef _COPY_TO_USER_SPACE_HXX_
00030 #define _COPY_TO_USER_SPACE_HXX_
00031 
00032 #include <string>
00033 #include <iostream>
00034 #include "CalciumPortTraits.hxx"
00035 
00036 #include <cstdio>
00037 
00038 //#define MYDEBUG
00039 
00040 //Les demandes de copies vers l'espace utilisateur
00041 //proviennent d'une procédure de lecture  
00042 
00043 
00044 //Cas du zero copie
00045 template <bool zerocopy, typename DataManipulator >
00046 struct Copy2UserSpace{
00047   
00048   template <class T1, class T2>
00049   static void apply( T1 * & data, T2 & corbaData, size_t nRead ){
00050 
00051      typedef typename DataManipulator::InnerType       InnerType;
00052 
00053     // OLD:Devient propriétaire des données contenues dans la structure CORBA
00054     // OLD:(allouées par allocbuff() pour une séquence)
00055     // OLD:Le client est propriétaire des données.
00056     // OLD:Il doit cependant être attentif au fait que s'il les modifie,
00057     // OLD:une nouvelle demande de lecture lui fournira les données modifiées.
00058     // OLD:TODO : Si plusieurs lecteurs demandent la même donnée, 
00059     // OLD:       ? qui devient le propriétaire? --> Forcément le premier car
00060     // OLD:       ensuite la séquence n'est plus propriétaire et rendra un pointeur NULL.
00061     // OLD:     NO: Le port devrait resté propriétaire du contenu de la séquence
00062     // OLD:     NO: L'utilisateur doit de toute les façons utiliser les données reçues en
00063     // OLD:     NO: lecture seulement car si une nouvelle demande de lecture est formulée
00064     // OLD:     NO: pour ces données, les eventuelles modifications seraient visibles !
00065     // OLD:YES : La solution de donner la propriété à l'utilisateur est convenable car si
00066     // OLD:le port déréférence ces données (garbage collecteur, niveau) le buffer
00067     // OLD:reste disponible à l'ulisateur en lecture et écriture
00068     // OLD:Le problème est que la donnée CORBA stockée par le port est maintenant vide (cf CORBA BOOK)
00069     // OLD:du coup quid d'une nouvelle demande de lecture : A TESTER 
00070 
00071      // Le PORT doit être capable de répondre aux demandes de lecture
00072      // multiples d'une donnée pour une même estampille et doit donc garder un pointeur valide
00073      // sur le buffer. Il se pose cependant un problème s'il décide
00074      // de supprimer la donnée alors que des client utilise le buffer (historique calcium) !
00075      // La seule façon de gérer proprement cette situation est d'utiliser un shared_pointer (TODO).
00076      // Pour l'instant l'utilisateur du mode zero copie doit s'assurer que le niveau d'historique
00077      // utilisé par le port est compatible avec son utilisation des buffers. Il doit
00078      // être également conscient que s'il modifie le buffer, il est modifié pour tous les
00079      // utilisateurs actuels et futurs.
00080     
00081      //REF:    InnerType * dataPtr  = DataManipulator::getPointer(corbaData,true);
00082      // Laisse la propriété des données à la structure CORBA
00083      // (buffer allouée par allocbuff() pour une séquence)
00084      InnerType * dataPtr  = DataManipulator::getPointer(corbaData,false);
00085 
00086     // Cette ligne poserait uun problème dans la méthode appelante, si elle
00087     // ne testait pas que les types utilisateurs et CORBA sont identiques :
00088     // ex :  InnerType == Corba::Long et d'un T == int
00089     // C'est l'objet de la spécialisation ci-dessous.
00090     data = dataPtr; 
00091 
00092     // En zero copie l'utilisateur doit appeler ecp_free ( cas ou un buffer intermédiaire
00093     // a été alloué pour cause de typage différent xor necessité de désalouer le buffer alloué par CORBA)
00094     // L'utilisateur doit cependant être attentif au fait qu'après désallocation, si la donnée
00095     // est toujours estampillée dans le port une nouvelle lecture pour cette estampille
00096     // rendrait un buffer vide.
00097   }
00098 };
00099 
00100 // Cas où il faut effectuer une recopie
00101 template <typename DataManipulator>
00102 struct Copy2UserSpace<false, DataManipulator> {
00103 
00104   //Recopie le contenu de la donnée CORBA dans le buffer utilisateur de longueur nRead
00105   template <class T1, class T2>
00106   static void apply( T1 * &data, T2 & corbaData, size_t nRead){
00107 
00108     typedef typename DataManipulator::InnerType        InnerType;
00109     
00110   
00111 #ifdef MYDEBUG
00112     InnerType * dataPtr = NULL;
00113     // Affiche la valeur du pointeur de la structure corba
00114     //  et les pointeurs contenus le cas échéant
00115     dataPtr  = DataManipulator::getPointer(corbaData,false);
00116     std::cerr << "-------- Copy2UserSpace<false> MARK 1a --dataPtr("<<dataPtr<<")[0.."<<
00117       DataManipulator::size(corbaData) <<"] : ----------------" << std::endl;
00118     std::copy(dataPtr,dataPtr+DataManipulator::size(corbaData),std::ostream_iterator<T1>(std::cerr," "));
00119     for (int i=0; i< DataManipulator::size(corbaData); ++i) 
00120       fprintf(stderr,"pointer[%d]=%p ",i, dataPtr[i]);
00121     std::cerr << std::endl;
00122 
00123     T1 * tmpData = data;
00124     //Cette affichage peut provoquer la détection d'écriture d'un espace non initailisé.
00125     std::cerr << "-------- Copy2UserSpace<false> MARK 1b --data("<<tmpData<<")[0.."<<
00126       DataManipulator::size(corbaData) <<"] : ----------------" << std::endl;
00127     std::copy(tmpData,tmpData+DataManipulator::size(corbaData),std::ostream_iterator<T1>(std::cerr," "));
00128     for (int i=0; i< DataManipulator::size(corbaData); ++i) 
00129       fprintf(stderr,"pointer[%d]=%p ",i, tmpData[i]);
00130     std::cerr << std::endl;
00131 #endif
00132 
00133     // Pour les types pointeurs et ref il faut effectuer une recopie profonde.
00134     // On la délègue au manipulateur de données. 
00135       
00136     // Recopie des données dans le buffer allouée par l'utilisateur 
00137     // OU 
00138     // Recopie des données dans le buffer allouée par la méthode appelante (ex: lecture)
00139     // dans le cas d'une demande utilisateur 0 copie mais que types utilisateurs et CORBA incompatibles.
00140     
00141     //std::copy(dataPtr,dataPtr+nRead,data);
00142     DataManipulator::copy(corbaData,data,nRead);
00143       
00144 #ifdef MYDEBUG
00145     tmpData = data;
00146     std::cerr << "-------- Copy2UserSpace<false> MARK 1c --data("<<tmpData<<")[0.."<<
00147       DataManipulator::size(corbaData) <<"] : ----------------" << std::endl;
00148     std::copy(tmpData,tmpData+DataManipulator::size(corbaData),std::ostream_iterator<T1>(std::cerr," "));
00149     for (int i=0; i< DataManipulator::size(corbaData); ++i) 
00150       fprintf(stderr,"pointer[%d]=%p ",i, tmpData[i]);
00151     std::cerr << std::endl;
00152 #endif
00153     
00154   }
00155   
00156 };
00157 
00158 
00159 // Désallocation des buffers si necessaire
00160 template <bool rel, typename DataManipulator >
00161 struct DeleteTraits {
00162   template <typename T> 
00163   static void apply(T * dataPtr) {
00164 
00165     typedef typename DataManipulator::Type         DataType; // Attention != T
00166     
00167     // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
00168     // la donnée corba associée à un DataId ! 
00169     // Ne pas effectuer la desallocation suivante :
00170     // DataManipulator::relPointer(dataPtr);
00171   }
00172 };
00173 
00174 // Désalocation du buffer intermédiaire 
00175 // dans le cas d'un type Utilisateur différent du type CORBA 
00176 template <typename DataManipulator>
00177 struct DeleteTraits< false, DataManipulator > {
00178 
00179   template <typename T> 
00180   static void apply(T * dataPtr) { delete[] dataPtr; }
00181 
00182 };
00183 
00184 #endif