Salome HOME
scotch6.0.4 needs pthread... Quick and dirty solution to be improved
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingRefCountObject.cxx
1 // Copyright (C) 2007-2016  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
24 #include "InterpKernelException.hxx"
25
26 #include <sstream>
27 #include <algorithm>
28
29 using namespace MEDCoupling;
30
31 GlobalDict *GlobalDict::UNIQUE_INSTANCE=0;
32
33 const char *MEDCoupling::MEDCouplingVersionStr()
34 {
35   return MEDCOUPLING_VERSION_STR;
36 }
37
38 int MEDCoupling::MEDCouplingVersion()
39 {
40   return MEDCOUPLING_VERSION;
41 }
42
43 void MEDCoupling::MEDCouplingVersionMajMinRel(int& maj, int& minor, int& releas)
44 {
45   int ver=MEDCOUPLING_VERSION;
46   maj=(ver & 0xFF0000) >> 16;
47   minor=(ver & 0xFF00) >> 8;
48   releas=(ver & 0xFF);
49 }
50
51 int MEDCoupling::MEDCouplingSizeOfVoidStar()
52 {
53   return 8*sizeof(std::size_t);
54 }
55
56 /*!
57  * If true is returned it is a LittleEndian machine.
58  * If false it is a BigEndian machine.
59  * \return the coding mode of integers of the machine.
60  */
61 bool MEDCoupling::MEDCouplingByteOrder()
62 {
63   unsigned int x(1);
64   unsigned char *xc(reinterpret_cast<unsigned char *>(&x));
65   return xc[0]==1;
66 }
67
68 const char *MEDCoupling::MEDCouplingByteOrderStr()
69 {
70   static const char LITTLEENDIAN_STR[]="LittleEndian";
71   static const char BIGENDIAN_STR[]="BigEndian";
72   if(MEDCouplingByteOrder())
73     return LITTLEENDIAN_STR;
74   else
75     return BIGENDIAN_STR;
76 }
77
78 bool MEDCoupling::IsCXX11Compiled()
79 {
80 #if __cplusplus >= 201103L
81   return true;
82 #else
83   return false;
84 #endif
85 }
86
87 //=
88
89 std::size_t BigMemoryObject::getHeapMemorySize() const
90 {
91   std::size_t ret(getHeapMemorySizeWithoutChildren());
92   std::vector<const BigMemoryObject *> v(getDirectChildren());
93   std::set<const BigMemoryObject *> s1,s2(v.begin(),v.end());
94   return ret+GetHeapMemoryOfSet(s1,s2);
95 }
96
97 /*!
98  * This method returns all the progeny of \a this (this is \b not included in returned vector).
99  * All the progeny means all the subobjects (children), subsubobjects (little children), ... of \a this.
100  * The elements in returned array are reported only once even if they appear several times in the progeny of \a this.
101  */
102 std::vector<const BigMemoryObject *> BigMemoryObject::getAllTheProgeny() const
103 {
104   std::vector<const BigMemoryObject *> s1(getDirectChildren());
105   std::vector<const BigMemoryObject *> ret;
106   while(!s1.empty())
107     {
108       ret.insert(ret.end(),s1.begin(),s1.end());
109       std::vector<const BigMemoryObject *> s3;
110       for(std::vector<const BigMemoryObject *>::const_iterator it0=s1.begin();it0!=s1.end();it0++)
111         {
112           std::vector<const BigMemoryObject *> s2;
113           if(*it0)
114             s2=(*it0)->getDirectChildren();
115           for(std::vector<const BigMemoryObject *>::const_iterator it1=s2.begin();it1!=s2.end();it1++)
116             {
117               if(*it1)
118                 if(std::find(ret.begin(),ret.end(),*it1)==ret.end())
119                   s3.push_back(*it1);
120             }
121         }
122       s1=s3;
123     }
124   return ret;
125 }
126
127 /*!
128  * This method scan all the progeny of \a this (\a this excluded) to see if \a obj is part of it.
129  * If obj is NULL false is returned.
130  * \sa BigMemoryObject::getAllTheProgeny
131  */
132 bool BigMemoryObject::isObjectInTheProgeny(const BigMemoryObject *obj) const
133 {
134   if(!obj)
135     return false;
136   std::vector<const BigMemoryObject *> objs(getAllTheProgeny());
137   return std::find(objs.begin(),objs.end(),obj)!=objs.end();
138 }
139
140 std::size_t BigMemoryObject::GetHeapMemorySizeOfObjs(const std::vector<const BigMemoryObject *>& objs)
141 {
142   std::size_t ret(0);
143   std::set<const BigMemoryObject *> s1,s2;
144   for(std::vector<const BigMemoryObject *>::const_iterator it0=objs.begin();it0!=objs.end();it0++)
145     {
146       if(*it0)
147         if(s1.find(*it0)==s1.end())
148           {
149             std::vector<const BigMemoryObject *> vTmp((*it0)->getDirectChildren());
150             s2.insert(vTmp.begin(),vTmp.end());
151             ret+=(*it0)->getHeapMemorySizeWithoutChildren();
152             s1.insert(*it0);
153           }
154     }
155   return ret+GetHeapMemoryOfSet(s1,s2);
156 }
157
158 std::size_t BigMemoryObject::GetHeapMemoryOfSet(std::set<const BigMemoryObject *>& s1, std::set<const BigMemoryObject *>& s2)
159 {
160   std::size_t ret(0);
161   while(!s2.empty())
162     {
163       std::set<const BigMemoryObject *> s3;
164       for(std::set<const BigMemoryObject *>::const_iterator it=s2.begin();it!=s2.end();it++)
165         {
166           if(s1.find(*it)==s1.end())
167             {
168               ret+=(*it)->getHeapMemorySizeWithoutChildren();
169               s1.insert(*it);
170               std::vector<const BigMemoryObject *> v2((*it)->getDirectChildren());
171               for(std::vector<const BigMemoryObject *>::const_iterator it2=v2.begin();it2!=v2.end();it2++)
172                 if(s1.find(*it2)==s1.end())
173                   s3.insert(*it2);
174             }
175         }
176       s2=s3;
177     }
178   return ret;
179 }
180
181 std::string BigMemoryObject::getHeapMemorySizeStr() const
182 {
183   static const char *UNITS[4]={"B","kB","MB","GB"};
184   std::size_t m(getHeapMemorySize());
185   std::ostringstream oss; oss.precision(3);
186   std::size_t remain(0);
187   int i(0);
188   for(;i<4;i++)
189     {
190       if(m<1024)
191         {
192           oss << m;
193           if(remain!=0)
194             {
195               std::ostringstream oss2; oss2 << std::fixed << ((double)remain)/1024.;
196               std::string s(oss2.str());
197               s=s.substr(1,4);
198               std::size_t pos(s.find_last_not_of('0'));
199               if(pos==4)
200                 oss << s;
201               else
202                 oss << s.substr(0,pos+1);
203             }
204           oss << " " << UNITS[i];
205           break;
206         }
207       else
208         {
209           if(i!=3)
210             {
211               remain=(m%1024);
212               m/=1024;
213             }
214         }
215     }
216   if(i==4)
217     oss << m << " " << UNITS[3];
218   return oss.str();
219 }
220
221 std::vector<const BigMemoryObject *> BigMemoryObject::getDirectChildren() const
222 {
223   std::vector<const BigMemoryObject *> ret;
224   std::vector<const BigMemoryObject *> retWithNull(getDirectChildrenWithNull());
225   for(std::vector<const BigMemoryObject *>::const_iterator it=retWithNull.begin();it!=retWithNull.end();it++)
226     if(*it)
227       ret.push_back(*it);
228   return ret;
229 }
230
231 BigMemoryObject::~BigMemoryObject()
232 {
233 }
234
235 //=
236
237 RefCountObjectOnly::RefCountObjectOnly():_cnt(1)
238 {
239 }
240
241 RefCountObjectOnly::RefCountObjectOnly(const RefCountObjectOnly& other):_cnt(1)
242 {
243 }
244
245 bool RefCountObjectOnly::decrRef() const
246 {
247   bool ret=((--_cnt)==0);
248   if(ret)
249     delete this;
250   return ret;
251 }
252
253 void RefCountObjectOnly::incrRef() const
254 {
255   _cnt++;
256 }
257
258 int RefCountObjectOnly::getRCValue() const
259 {
260   return _cnt;
261 }
262
263 RefCountObjectOnly::~RefCountObjectOnly()
264 {
265 }
266
267 /*!
268  * Do nothing here ! It is not a bug ( I hope :) ) because all subclasses that
269  * copies using operator= should not copy the ref counter of \a other !
270  */
271 RefCountObjectOnly& RefCountObjectOnly::operator=(const RefCountObjectOnly& other)
272 {
273   return *this;
274 }
275
276 //=
277
278 RefCountObject::RefCountObject()
279 {
280 }
281
282 RefCountObject::RefCountObject(const RefCountObject& other):RefCountObjectOnly(other)
283 {
284 }
285
286 RefCountObject::~RefCountObject()
287 {
288 }
289
290 //=
291
292 GlobalDict *GlobalDict::GetInstance()
293 {
294   if(!UNIQUE_INSTANCE)
295     UNIQUE_INSTANCE=new GlobalDict;
296   return UNIQUE_INSTANCE;
297 }
298
299 bool GlobalDict::hasKey(const std::string& key) const
300 {
301   std::map<std::string, std::string>::const_iterator it(_my_map.find(key));
302   return it!=_my_map.end();
303 }
304
305 std::string GlobalDict::value(const std::string& key) const
306 {
307   std::map<std::string, std::string>::const_iterator it(_my_map.find(key));
308   if(it==_my_map.end())
309     {
310       std::ostringstream oss;
311       oss << "GlobalDict::value : key \"" << key << "\" is not in map !";
312       throw INTERP_KERNEL::Exception(oss.str().c_str());
313     }
314   return (*it).second;
315 }
316
317 std::vector<std::string> GlobalDict::keys() const
318 {
319   std::vector<std::string> ret;
320   for(std::map<std::string, std::string>::const_iterator it=_my_map.begin();it!=_my_map.end();it++)
321     ret.push_back((*it).first);
322   return ret;
323 }
324
325 void GlobalDict::erase(const std::string& key)
326 {
327   std::map<std::string, std::string>::iterator it(_my_map.find(key));
328   if(it==_my_map.end())
329     {
330       std::ostringstream oss;
331       oss << "GlobalDict::erase : key \"" << key << "\" is not in map !";
332       throw INTERP_KERNEL::Exception(oss.str().c_str());
333     }
334   _my_map.erase(it);
335 }
336
337 void GlobalDict::clear()
338 {
339   _my_map.clear();
340 }
341
342 void GlobalDict::setKeyValue(const std::string& key, const std::string& val)
343 {
344   std::map<std::string, std::string>::const_iterator it(_my_map.find(key));
345   if(it!=_my_map.end())
346     {
347       std::ostringstream oss;
348       oss << "GlobalDict::setKeyValue : key \"" << key << "\" already exists !";
349       throw INTERP_KERNEL::Exception(oss.str().c_str());
350     }
351   _my_map[key]=val;
352 }
353
354 void GlobalDict::setKeyValueForce(const std::string& key, const std::string& val)
355 {
356   _my_map[key]=val;
357 }
358
359 std::string GlobalDict::printSelf() const
360 {
361   std::ostringstream oss;
362   for(std::map<std::string, std::string>::const_iterator it=_my_map.begin();it!=_my_map.end();it++)
363     {
364       oss << "(" << (*it).first << "," << (*it).second << ")" << std::endl;
365     }
366   return oss.str();
367 }