b311480e |
1 | // Created on: 2005-03-15 |
2 | // Created by: Peter KURNEV |
3 | // Copyright (c) 1998-1999 Matra Datavision |
4 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
5 | // |
6 | // The content of this file is subject to the Open CASCADE Technology Public |
7 | // License Version 6.5 (the "License"). You may not use the content of this file |
8 | // except in compliance with the License. Please obtain a copy of the License |
9 | // at http://www.opencascade.org and read it completely before using this file. |
10 | // |
11 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
12 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
13 | // |
14 | // The Original Code and all software distributed under the License is |
15 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
16 | // Initial Developer hereby disclaims all such warranties, including without |
17 | // limitation, any warranties of merchantability, fitness for a particular |
18 | // purpose or non-infringement. Please see the License for the specific terms |
19 | // and conditions governing the rights and limitations under the License. |
20 | |
7fd59977 |
21 | |
22 | |
23 | #include <Standard.ixx> |
24 | |
25 | #include <stdlib.h> |
26 | |
27 | #include <Standard_MMgrOpt.hxx> |
28 | #include <Standard_MMgrRaw.hxx> |
29 | #include <Standard_MMgrTBBalloc.hxx> |
30 | |
af09dbff |
31 | #if(defined(_WIN32) || defined(__WIN32__)) |
32 | #include <windows.h> |
33 | #include <malloc.h> |
34 | #endif |
35 | |
7fd59977 |
36 | // Global reentrant flag |
af09dbff |
37 | static Standard_Boolean Standard_IsReentrant = Standard_True; |
7fd59977 |
38 | |
39 | //======================================================================= |
40 | //class : Standard_MMgrFactory |
41 | //purpose : Container for pointer to memory manager; |
42 | // used to construct appropriate memory manager according |
43 | // to environment settings, and to ensure destruction upon exit |
44 | //======================================================================= |
45 | |
46 | class Standard_MMgrFactory { |
47 | public: |
48 | Standard_MMgrFactory(); |
49 | ~Standard_MMgrFactory(); |
50 | public: |
51 | Standard_MMgrRoot* myFMMgr; |
52 | }; |
53 | |
54 | //======================================================================= |
55 | //function : Standard_MMgrFactory |
56 | //purpose : Check environment variables and create appropriate memory manager |
57 | //======================================================================= |
58 | |
af09dbff |
59 | Standard_MMgrFactory::Standard_MMgrFactory() |
60 | : myFMMgr (NULL) |
7fd59977 |
61 | { |
af09dbff |
62 | char* aVar; |
63 | Standard_Integer anAllocId = (aVar = getenv ("MMGT_OPT" )) ? atoi (aVar) : 0; |
64 | Standard_Boolean toClear = (aVar = getenv ("MMGT_CLEAR" )) ? (atoi (aVar) != 0) : Standard_True; |
65 | |
66 | |
67 | // on Windows (actual for XP and 2000) activate low fragmentation heap |
68 | // for CRT heap in order to get best performance. |
69 | // Environment variable MMGT_LFH can be used to switch off this action (if set to 0) |
70 | #if defined(_MSC_VER) |
71 | aVar = getenv ("MMGT_LFH"); |
72 | if ( aVar == NULL || atoi (aVar) != 0 ) |
73 | { |
74 | ULONG aHeapInfo = 2; |
75 | HANDLE aCRTHeap = (HANDLE)_get_heap_handle(); |
76 | HeapSetInformation (aCRTHeap, HeapCompatibilityInformation, &aHeapInfo, sizeof(aHeapInfo)); |
7fd59977 |
77 | } |
af09dbff |
78 | #endif |
79 | |
80 | aVar = getenv ("MMGT_REENTRANT"); |
81 | if ( aVar != NULL ) |
82 | Standard_IsReentrant = (atoi (aVar) != 0); |
7fd59977 |
83 | |
af09dbff |
84 | switch (anAllocId) |
85 | { |
86 | case 1: // OCCT optimized memory allocator |
87 | { |
88 | Standard_Boolean bMMap = (aVar = getenv ("MMGT_MMAP" )) ? (atoi (aVar) != 0) : Standard_True; |
89 | Standard_Integer aCellSize = (aVar = getenv ("MMGT_CELLSIZE" )) ? atoi (aVar) : 200; |
90 | Standard_Integer aNbPages = (aVar = getenv ("MMGT_NBPAGES" )) ? atoi (aVar) : 1000; |
91 | Standard_Integer aThreshold = (aVar = getenv ("MMGT_THRESHOLD")) ? atoi (aVar) : 40000; |
92 | myFMMgr = new Standard_MMgrOpt (toClear, bMMap, aCellSize, aNbPages, aThreshold, Standard_IsReentrant); |
93 | break; |
94 | } |
95 | case 2: // TBB memory allocator |
96 | myFMMgr = new Standard_MMgrTBBalloc (toClear); |
97 | break; |
98 | case 0: |
99 | default: // system default memory allocator |
100 | myFMMgr = new Standard_MMgrRaw (toClear); |
101 | } |
7fd59977 |
102 | } |
103 | |
104 | //======================================================================= |
105 | //function : ~Standard_MMgrFactory |
106 | //purpose : |
107 | //======================================================================= |
108 | |
109 | Standard_MMgrFactory::~Standard_MMgrFactory() |
110 | { |
207e57e4 |
111 | if ( myFMMgr ) { |
7fd59977 |
112 | myFMMgr->Purge(Standard_True); |
113 | // delete myFMMgr; |
114 | // myFMMgr = 0; |
115 | } |
116 | } |
117 | |
118 | //======================================================================= |
119 | // function: GetMMgr |
120 | // |
121 | // This static function has a purpose to wrap static holder for memory |
122 | // manager instance. |
123 | // |
124 | // Wrapping holder inside a function is needed to ensure that it will |
125 | // be initialized not later than the first call to memory manager (that |
126 | // would be impossible to guarantee if holder was static variable on |
127 | // global or file scope, because memory manager may be called from |
128 | // constructors of other static objects). |
129 | // |
130 | // Note that at the same time we could not guarantee that the holder |
131 | // object is destroyed after last call to memory manager, since that |
132 | // last call may be from static Handle() object which has been initialized |
133 | // dynamically during program execution rather than in its constructor. |
134 | // |
135 | // Therefore holder currently does not call destructor of the memory manager |
136 | // but only its method Purge() with Standard_True. |
137 | // |
138 | // To free the memory completely, we probably could use compiler-specific |
139 | // pragmas (such as '#pragma fini' on SUN Solaris and '#pragma init_seg' on |
140 | // WNT MSVC++) to put destructing function in code segment that is called |
141 | // after destructors of other (even static) objects. However, this is not |
142 | // done by the moment since it is compiler-dependent and there is no guarantee |
143 | // thatsome other object calling memory manager is not placed also in that segment... |
144 | // |
145 | // Note that C runtime function atexit() could not help in this problem |
146 | // since its behaviour is the same as for destructors of static objects |
147 | // (see ISO 14882:1998 "Programming languages -- C++" 3.6.3) |
148 | // |
149 | // The correct approach to deal with the problem would be to have memory manager |
150 | // to properly control its memory allocation and caching free blocks so |
151 | // as to release all memory as soon as it is returned to it, and probably |
152 | // even delete itself if all memory it manages has been released and |
153 | // last call to method Purge() was with True. |
154 | // |
155 | // Note that one possible method to control memory allocations could |
156 | // be counting calls to Allocate() and Free()... |
157 | // |
158 | //======================================================================= |
159 | |
160 | static Standard_MMgrRoot* GetMMgr() |
161 | { |
162 | static Standard_MMgrFactory aFactory; |
163 | return aFactory.myFMMgr; |
164 | } |
165 | |
166 | //======================================================================= |
167 | //function : Allocate |
168 | //purpose : |
169 | //======================================================================= |
170 | |
171 | Standard_Address Standard::Allocate(const Standard_Size size) |
172 | { |
173 | return GetMMgr()->Allocate(size); |
174 | } |
175 | |
176 | //======================================================================= |
177 | //function : Free |
178 | //purpose : |
179 | //======================================================================= |
180 | |
181 | void Standard::Free(Standard_Address& aStorage) |
182 | { |
183 | GetMMgr()->Free(aStorage); |
184 | } |
185 | |
186 | //======================================================================= |
187 | //function : Reallocate |
188 | //purpose : |
189 | //======================================================================= |
190 | |
191 | Standard_Address Standard::Reallocate(Standard_Address& aStorage, |
192 | const Standard_Size newSize) |
193 | { |
194 | return GetMMgr()->Reallocate(aStorage, newSize); |
195 | } |
196 | |
197 | //======================================================================= |
198 | //function : Purge |
199 | //purpose : |
200 | //======================================================================= |
201 | |
202 | Standard_Integer Standard::Purge() |
203 | { |
204 | return GetMMgr()->Purge(); |
205 | } |
206 | |
207 | //======================================================================= |
208 | //function : IsReentrant |
209 | //purpose : |
210 | //======================================================================= |
211 | |
212 | Standard_Boolean Standard::IsReentrant() |
213 | { |
214 | return Standard_IsReentrant; |
215 | } |
216 | |
217 | //======================================================================= |
218 | //function : SetReentrant |
219 | //purpose : |
220 | //======================================================================= |
221 | |
222 | void Standard::SetReentrant (const Standard_Boolean isReentrant) |
223 | { |
224 | Standard_IsReentrant = isReentrant; |
225 | GetMMgr()->SetReentrant (isReentrant); |
226 | } |