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