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
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.
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.
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.
23 #include <Standard.ixx>
27 #include <Standard_MMgrOpt.hxx>
28 #include <Standard_MMgrRaw.hxx>
29 #include <Standard_MMgrTBBalloc.hxx>
31 #if(defined(_WIN32) || defined(__WIN32__))
36 // Global reentrant flag
37 static Standard_Boolean Standard_IsReentrant = Standard_True;
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 //=======================================================================
46 class Standard_MMgrFactory {
48 Standard_MMgrFactory();
49 ~Standard_MMgrFactory();
51 Standard_MMgrRoot* myFMMgr;
54 //=======================================================================
55 //function : Standard_MMgrFactory
56 //purpose : Check environment variables and create appropriate memory manager
57 //=======================================================================
59 Standard_MMgrFactory::Standard_MMgrFactory()
63 Standard_Integer anAllocId = (aVar = getenv ("MMGT_OPT" )) ? atoi (aVar) : 0;
64 Standard_Boolean toClear = (aVar = getenv ("MMGT_CLEAR" )) ? (atoi (aVar) != 0) : Standard_True;
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)
71 aVar = getenv ("MMGT_LFH");
72 if ( aVar == NULL || atoi (aVar) != 0 )
75 HANDLE aCRTHeap = (HANDLE)_get_heap_handle();
76 HeapSetInformation (aCRTHeap, HeapCompatibilityInformation, &aHeapInfo, sizeof(aHeapInfo));
80 aVar = getenv ("MMGT_REENTRANT");
82 Standard_IsReentrant = (atoi (aVar) != 0);
86 case 1: // OCCT optimized memory allocator
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);
95 case 2: // TBB memory allocator
96 myFMMgr = new Standard_MMgrTBBalloc (toClear);
99 default: // system default memory allocator
100 myFMMgr = new Standard_MMgrRaw (toClear);
104 //=======================================================================
105 //function : ~Standard_MMgrFactory
107 //=======================================================================
109 Standard_MMgrFactory::~Standard_MMgrFactory()
112 myFMMgr->Purge(Standard_True);
118 //=======================================================================
121 // This static function has a purpose to wrap static holder for memory
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).
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.
135 // Therefore holder currently does not call destructor of the memory manager
136 // but only its method Purge() with Standard_True.
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...
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)
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.
155 // Note that one possible method to control memory allocations could
156 // be counting calls to Allocate() and Free()...
158 //=======================================================================
160 static Standard_MMgrRoot* GetMMgr()
162 static Standard_MMgrFactory aFactory;
163 return aFactory.myFMMgr;
166 //=======================================================================
167 //function : Allocate
169 //=======================================================================
171 Standard_Address Standard::Allocate(const Standard_Size size)
173 return GetMMgr()->Allocate(size);
176 //=======================================================================
179 //=======================================================================
181 void Standard::Free(Standard_Address& aStorage)
183 GetMMgr()->Free(aStorage);
186 //=======================================================================
187 //function : Reallocate
189 //=======================================================================
191 Standard_Address Standard::Reallocate(Standard_Address& aStorage,
192 const Standard_Size newSize)
194 return GetMMgr()->Reallocate(aStorage, newSize);
197 //=======================================================================
200 //=======================================================================
202 Standard_Integer Standard::Purge()
204 return GetMMgr()->Purge();
207 //=======================================================================
208 //function : IsReentrant
210 //=======================================================================
212 Standard_Boolean Standard::IsReentrant()
214 return Standard_IsReentrant;
217 //=======================================================================
218 //function : SetReentrant
220 //=======================================================================
222 void Standard::SetReentrant (const Standard_Boolean isReentrant)
224 Standard_IsReentrant = isReentrant;
225 GetMMgr()->SetReentrant (isReentrant);