Salome HOME
Copyright update 2021
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingRefCountObject.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingRefCountObject.hxx"
22 #include "MEDCoupling_version.h"
23 #include "MCType.hxx"
24
25 #include "InterpKernelException.hxx"
26
27 #include <sstream>
28 #include <algorithm>
29
30 using namespace MEDCoupling;
31
32 GlobalDict *GlobalDict::UNIQUE_INSTANCE=0;
33
34 const char *MEDCoupling::MEDCouplingVersionStr()
35 {
36   return MEDCOUPLING_VERSION_STR;
37 }
38
39 int MEDCoupling::MEDCouplingVersion()
40 {
41   return MEDCOUPLING_VERSION;
42 }
43
44 void MEDCoupling::MEDCouplingVersionMajMinRel(int& maj, int& minor, int& releas)
45 {
46   int ver=MEDCOUPLING_VERSION;
47   maj=(ver & 0xFF0000) >> 16;
48   minor=(ver & 0xFF00) >> 8;
49   releas=(ver & 0xFF);
50 }
51
52 int MEDCoupling::MEDCouplingSizeOfVoidStar()
53 {
54   return 8*sizeof(std::size_t);
55 }
56
57 std::size_t MEDCoupling::MEDCouplingSizeOfIDs()
58 {
59   return 8*sizeof(mcIdType);
60 }
61
62 /*!
63  * If true is returned it is a LittleEndian machine.
64  * If false it is a BigEndian machine.
65  * \return the coding mode of integers of the machine.
66  */
67 bool MEDCoupling::MEDCouplingByteOrder()
68 {
69   unsigned int x(1);
70   unsigned char *xc(reinterpret_cast<unsigned char *>(&x));
71   return xc[0]==1;
72 }
73
74 const char *MEDCoupling::MEDCouplingByteOrderStr()
75 {
76   static const char LITTLEENDIAN_STR[]="LittleEndian";
77   static const char BIGENDIAN_STR[]="BigEndian";
78   if(MEDCouplingByteOrder())
79     return LITTLEENDIAN_STR;
80   else
81     return BIGENDIAN_STR;
82 }
83
84 bool MEDCoupling::IsCXX11Compiled()
85 {
86   return true;
87 }
88
89 //=
90
91 std::string BigMemoryObject::debugHeapMemorySize() const
92 {
93   std::size_t ret(getHeapMemorySizeWithoutChildren()),sum(ret);
94   std::ostringstream oss;
95   std::vector<const BigMemoryObject *> s2(getDirectChildren());
96   std::set<const BigMemoryObject *> s1;
97   oss << "this (" << this->getClassName() << ") -> " << ret << std::endl;
98   while(!s2.empty())
99     {
100       std::vector<const BigMemoryObject *> s3;
101       for(auto it : s2)
102         {
103           if(s1.find(it)==s1.end())
104             {
105               ret = it->getHeapMemorySizeWithoutChildren(); sum+=ret;
106               oss << it->getClassName() << " -> " <<  ret << std::endl;
107               s1.insert(it);
108               std::vector<const BigMemoryObject *> v2(it->getDirectChildren());
109               for(auto it2 : v2)
110                 if(s1.find(it2)==s1.end())
111                   s3.push_back(it2);
112             }
113         }
114       s2=s3;
115     }
116   oss << "sum = " << sum << std::endl;
117   return oss.str();
118 }
119
120 std::size_t BigMemoryObject::getHeapMemorySize() const
121 {
122   std::size_t ret(getHeapMemorySizeWithoutChildren());
123   std::vector<const BigMemoryObject *> v(getDirectChildren());
124   std::set<const BigMemoryObject *> s1,s2(v.begin(),v.end());
125   return ret+GetHeapMemoryOfSet(s1,s2);
126 }
127
128 /*!
129  * This method returns all the progeny of \a this (this is \b not included in returned vector).
130  * All the progeny means all the subobjects (children), subsubobjects (little children), ... of \a this.
131  * The elements in returned array are reported only once even if they appear several times in the progeny of \a this.
132  */
133 std::vector<const BigMemoryObject *> BigMemoryObject::getAllTheProgeny() const
134 {
135   std::vector<const BigMemoryObject *> s1(getDirectChildren());
136   std::vector<const BigMemoryObject *> ret;
137   while(!s1.empty())
138     {
139       ret.insert(ret.end(),s1.begin(),s1.end());
140       std::vector<const BigMemoryObject *> s3;
141       for(std::vector<const BigMemoryObject *>::const_iterator it0=s1.begin();it0!=s1.end();it0++)
142         {
143           std::vector<const BigMemoryObject *> s2;
144           if(*it0)
145             s2=(*it0)->getDirectChildren();
146           for(std::vector<const BigMemoryObject *>::const_iterator it1=s2.begin();it1!=s2.end();it1++)
147             {
148               if(*it1)
149                 if(std::find(ret.begin(),ret.end(),*it1)==ret.end())
150                   s3.push_back(*it1);
151             }
152         }
153       s1=s3;
154     }
155   return ret;
156 }
157
158 /*!
159  * This method scan all the progeny of \a this (\a this excluded) to see if \a obj is part of it.
160  * If obj is NULL false is returned.
161  * \sa BigMemoryObject::getAllTheProgeny
162  */
163 bool BigMemoryObject::isObjectInTheProgeny(const BigMemoryObject *obj) const
164 {
165   if(!obj)
166     return false;
167   std::vector<const BigMemoryObject *> objs(getAllTheProgeny());
168   return std::find(objs.begin(),objs.end(),obj)!=objs.end();
169 }
170
171 std::size_t BigMemoryObject::GetHeapMemorySizeOfObjs(const std::vector<const BigMemoryObject *>& objs)
172 {
173   std::size_t ret(0);
174   std::set<const BigMemoryObject *> s1,s2;
175   for(std::vector<const BigMemoryObject *>::const_iterator it0=objs.begin();it0!=objs.end();it0++)
176     {
177       if(*it0)
178         if(s1.find(*it0)==s1.end())
179           {
180             std::vector<const BigMemoryObject *> vTmp((*it0)->getDirectChildren());
181             s2.insert(vTmp.begin(),vTmp.end());
182             ret+=(*it0)->getHeapMemorySizeWithoutChildren();
183             s1.insert(*it0);
184           }
185     }
186   return ret+GetHeapMemoryOfSet(s1,s2);
187 }
188
189 std::size_t BigMemoryObject::GetHeapMemoryOfSet(std::set<const BigMemoryObject *>& s1, std::set<const BigMemoryObject *>& s2)
190 {
191   std::size_t ret(0);
192   while(!s2.empty())
193     {
194       std::set<const BigMemoryObject *> s3;
195       for(std::set<const BigMemoryObject *>::const_iterator it=s2.begin();it!=s2.end();it++)
196         {
197           if(s1.find(*it)==s1.end())
198             {
199               ret+=(*it)->getHeapMemorySizeWithoutChildren();
200               s1.insert(*it);
201               std::vector<const BigMemoryObject *> v2((*it)->getDirectChildren());
202               for(std::vector<const BigMemoryObject *>::const_iterator it2=v2.begin();it2!=v2.end();it2++)
203                 if(s1.find(*it2)==s1.end())
204                   s3.insert(*it2);
205             }
206         }
207       s2=s3;
208     }
209   return ret;
210 }
211
212 std::string BigMemoryObject::getHeapMemorySizeStr() const
213 {
214   static const char *UNITS[4]={"B","kB","MB","GB"};
215   std::size_t m(getHeapMemorySize());
216   std::ostringstream oss; oss.precision(3);
217   std::size_t remain(0);
218   int i(0);
219   for(;i<4;i++)
220     {
221       if(m<1024)
222         {
223           oss << m;
224           if(remain!=0)
225             {
226               std::ostringstream oss2; oss2 << std::fixed << ((double)remain)/1024.;
227               std::string s(oss2.str());
228               s=s.substr(1,4);
229               std::size_t pos(s.find_last_not_of('0'));
230               if(pos==4)
231                 oss << s;
232               else
233                 oss << s.substr(0,pos+1);
234             }
235           oss << " " << UNITS[i];
236           break;
237         }
238       else
239         {
240           if(i!=3)
241             {
242               remain=(m%1024);
243               m/=1024;
244             }
245         }
246     }
247   if(i==4)
248     oss << m << " " << UNITS[3];
249   return oss.str();
250 }
251
252 std::vector<const BigMemoryObject *> BigMemoryObject::getDirectChildren() const
253 {
254   std::vector<const BigMemoryObject *> ret;
255   std::vector<const BigMemoryObject *> retWithNull(getDirectChildrenWithNull());
256   for(std::vector<const BigMemoryObject *>::const_iterator it=retWithNull.begin();it!=retWithNull.end();it++)
257     if(*it)
258       ret.push_back(*it);
259   return ret;
260 }
261
262 BigMemoryObject::~BigMemoryObject()
263 {
264 }
265
266 //=
267
268 RefCountObjectOnly::RefCountObjectOnly():_cnt(1)
269 {
270 }
271
272 RefCountObjectOnly::RefCountObjectOnly(const RefCountObjectOnly& other):_cnt(1)
273 {
274 }
275
276 bool RefCountObjectOnly::decrRef() const
277 {
278   bool ret=((--_cnt)==0);
279   if(ret)
280     delete this;
281   return ret;
282 }
283
284 void RefCountObjectOnly::incrRef() const
285 {
286   _cnt++;
287 }
288
289 int RefCountObjectOnly::getRCValue() const
290 {
291   return _cnt;
292 }
293
294 RefCountObjectOnly::~RefCountObjectOnly()
295 {
296 }
297
298 /*!
299  * Do nothing here ! It is not a bug ( I hope :) ) because all subclasses that
300  * copies using operator= should not copy the ref counter of \a other !
301  */
302 RefCountObjectOnly& RefCountObjectOnly::operator=(const RefCountObjectOnly& other)
303 {
304   return *this;
305 }
306
307 //=
308
309 RefCountObject::RefCountObject()
310 {
311 }
312
313 RefCountObject::RefCountObject(const RefCountObject& other):RefCountObjectOnly(other)
314 {
315 }
316
317 RefCountObject::~RefCountObject()
318 {
319 }
320
321 //=
322
323 GlobalDict *GlobalDict::GetInstance()
324 {
325   if(!UNIQUE_INSTANCE)
326     UNIQUE_INSTANCE=new GlobalDict;
327   return UNIQUE_INSTANCE;
328 }
329
330 bool GlobalDict::hasKey(const std::string& key) const
331 {
332   std::map<std::string, std::string>::const_iterator it(_my_map.find(key));
333   return it!=_my_map.end();
334 }
335
336 std::string GlobalDict::value(const std::string& key) const
337 {
338   std::map<std::string, std::string>::const_iterator it(_my_map.find(key));
339   if(it==_my_map.end())
340     {
341       std::ostringstream oss;
342       oss << "GlobalDict::value : key \"" << key << "\" is not in map !";
343       throw INTERP_KERNEL::Exception(oss.str().c_str());
344     }
345   return (*it).second;
346 }
347
348 std::vector<std::string> GlobalDict::keys() const
349 {
350   std::vector<std::string> ret;
351   for(std::map<std::string, std::string>::const_iterator it=_my_map.begin();it!=_my_map.end();it++)
352     ret.push_back((*it).first);
353   return ret;
354 }
355
356 void GlobalDict::erase(const std::string& key)
357 {
358   std::map<std::string, std::string>::iterator it(_my_map.find(key));
359   if(it==_my_map.end())
360     {
361       std::ostringstream oss;
362       oss << "GlobalDict::erase : key \"" << key << "\" is not in map !";
363       throw INTERP_KERNEL::Exception(oss.str().c_str());
364     }
365   _my_map.erase(it);
366 }
367
368 void GlobalDict::clear()
369 {
370   _my_map.clear();
371 }
372
373 void GlobalDict::setKeyValue(const std::string& key, const std::string& val)
374 {
375   std::map<std::string, std::string>::const_iterator it(_my_map.find(key));
376   if(it!=_my_map.end())
377     {
378       std::ostringstream oss;
379       oss << "GlobalDict::setKeyValue : key \"" << key << "\" already exists !";
380       throw INTERP_KERNEL::Exception(oss.str().c_str());
381     }
382   _my_map[key]=val;
383 }
384
385 void GlobalDict::setKeyValueForce(const std::string& key, const std::string& val)
386 {
387   _my_map[key]=val;
388 }
389
390 std::string GlobalDict::printSelf() const
391 {
392   std::ostringstream oss;
393   for(std::map<std::string, std::string>::const_iterator it=_my_map.begin();it!=_my_map.end();it++)
394     {
395       oss << "(" << (*it).first << "," << (*it).second << ")" << std::endl;
396     }
397   return oss.str();
398 }