Integration of OCCT 6.5.0 from SVN
[occt.git] / src / Standard / Standard.cxx
1 // File:        Standard.cxx
2 // Created:     Tue Mar 15 17:33:31 2005
3 // Author:      Peter KURNEV
4 //              <pkv@irinox>
5
6
7 #include <Standard.ixx>
8
9 #include <stdlib.h>
10
11 #include <Standard_MMgrOpt.hxx>
12 #include <Standard_MMgrRaw.hxx>
13 #include <Standard_MMgrTBBalloc.hxx>
14
15 // Global reentrant flag
16 static Standard_Boolean Standard_IsReentrant = Standard_False;
17
18 //=======================================================================
19 //class    : Standard_MMgrFactory 
20 //purpose  : Container for pointer to memory manager;
21 //           used to construct appropriate memory manager according
22 //           to environment settings, and to ensure destruction upon exit
23 //=======================================================================
24
25 class Standard_MMgrFactory {
26  public:
27   Standard_MMgrFactory();
28   ~Standard_MMgrFactory();
29  public:
30   Standard_MMgrRoot* myFMMgr;
31 };
32
33 //=======================================================================
34 //function : Standard_MMgrFactory
35 //purpose  : Check environment variables and create appropriate memory manager
36 //=======================================================================
37
38 Standard_MMgrFactory::Standard_MMgrFactory() : myFMMgr(0)
39 {
40   char *var;
41   Standard_Boolean bClear, bMMap, bReentrant;
42   Standard_Integer aCellSize, aNbPages, aThreshold, bOptAlloc;
43   //
44   bOptAlloc   = atoi((var = getenv("MMGT_OPT"      )) ? var : "1"    ); 
45   bClear      = atoi((var = getenv("MMGT_CLEAR"    )) ? var : "1"    );
46   bMMap       = atoi((var = getenv("MMGT_MMAP"     )) ? var : "1"    ); 
47   aCellSize   = atoi((var = getenv("MMGT_CELLSIZE" )) ? var : "200"  ); 
48   aNbPages    = atoi((var = getenv("MMGT_NBPAGES"  )) ? var : "1000" );
49   aThreshold  = atoi((var = getenv("MMGT_THRESHOLD")) ? var : "40000");
50   bReentrant  = atoi((var = getenv("MMGT_REENTRANT")) ? var : "0"    );
51   
52   if ( bOptAlloc == 1 ) { 
53     myFMMgr = new Standard_MMgrOpt(bClear, bMMap, aCellSize, aNbPages,
54                                    aThreshold, bReentrant);
55   }
56   else if ( bOptAlloc == 2 ) {
57     myFMMgr = new Standard_MMgrTBBalloc(bClear);
58   }
59   else {
60     myFMMgr = new Standard_MMgrRaw(bClear);
61   }
62
63   // Set grobal reentrant flag according to MMGT_REENTRANT environment variable
64   if ( ! Standard_IsReentrant )
65     Standard_IsReentrant = bReentrant;
66 }
67
68 //=======================================================================
69 //function : ~Standard_MMgrFactory
70 //purpose  : 
71 //=======================================================================
72
73 Standard_MMgrFactory::~Standard_MMgrFactory()
74 {
75   if ( ! myFMMgr ) {
76     myFMMgr->Purge(Standard_True);
77 //  delete myFMMgr;
78 //  myFMMgr = 0;  
79   }
80 }
81
82 //=======================================================================
83 // function: GetMMgr
84 //
85 // This static function has a purpose to wrap static holder for memory 
86 // manager instance. 
87 //
88 // Wrapping holder inside a function is needed to ensure that it will
89 // be initialized not later than the first call to memory manager (that
90 // would be impossible to guarantee if holder was static variable on 
91 // global or file scope, because memory manager may be called from 
92 // constructors of other static objects).
93 //
94 // Note that at the same time we could not guarantee that the holder 
95 // object is destroyed after last call to memory manager, since that 
96 // last call may be from static Handle() object which has been initialized
97 // dynamically during program execution rather than in its constructor.
98 //
99 // Therefore holder currently does not call destructor of the memory manager 
100 // but only its method Purge() with Standard_True.
101 //
102 // To free the memory completely, we probably could use compiler-specific 
103 // pragmas (such as '#pragma fini' on SUN Solaris and '#pragma init_seg' on 
104 // WNT MSVC++) to put destructing function in code segment that is called
105 // after destructors of other (even static) objects. However, this is not 
106 // done by the moment since it is compiler-dependent and there is no guarantee 
107 // thatsome other object calling memory manager is not placed also in that segment...
108 //
109 // Note that C runtime function atexit() could not help in this problem 
110 // since its behaviour is the same as for destructors of static objects 
111 // (see ISO 14882:1998 "Programming languages -- C++" 3.6.3)
112 //
113 // The correct approach to deal with the problem would be to have memory manager 
114 // to properly control its memory allocation and caching free blocks so 
115 // as to release all memory as soon as it is returned to it, and probably
116 // even delete itself if all memory it manages has been released and 
117 // last call to method Purge() was with True.
118 //
119 // Note that one possible method to control memory allocations could
120 // be counting calls to Allocate() and Free()...
121 //
122 //=======================================================================
123
124 static Standard_MMgrRoot* GetMMgr()
125 {
126   static Standard_MMgrFactory aFactory;
127   return aFactory.myFMMgr;
128 }
129
130 //=======================================================================
131 //function : Allocate
132 //purpose  : 
133 //=======================================================================
134
135 Standard_Address Standard::Allocate(const Standard_Size size)
136 {
137   return GetMMgr()->Allocate(size);
138 }
139
140 //=======================================================================
141 //function : Free
142 //purpose  : 
143 //=======================================================================
144
145 void Standard::Free(Standard_Address& aStorage)
146 {
147   GetMMgr()->Free(aStorage);
148 }
149
150 //=======================================================================
151 //function : Reallocate
152 //purpose  : 
153 //=======================================================================
154
155 Standard_Address Standard::Reallocate(Standard_Address& aStorage,
156                                       const Standard_Size newSize)
157 {
158   return GetMMgr()->Reallocate(aStorage, newSize);
159 }
160
161 //=======================================================================
162 //function : Purge
163 //purpose  : 
164 //=======================================================================
165
166 Standard_Integer Standard::Purge()
167 {
168   return GetMMgr()->Purge();
169 }
170
171 //=======================================================================
172 //function : IsReentrant
173 //purpose  : 
174 //=======================================================================
175
176 Standard_Boolean Standard::IsReentrant()
177 {
178   return Standard_IsReentrant;
179 }
180
181 //=======================================================================
182 //function : SetReentrant
183 //purpose  : 
184 //=======================================================================
185
186 void Standard::SetReentrant (const Standard_Boolean isReentrant)
187 {
188   Standard_IsReentrant = isReentrant;
189   GetMMgr()->SetReentrant (isReentrant);
190 }