0022627: Change OCCT memory management defaults
[occt.git] / src / MMgt / MMgt_StackManager.cxx
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <MMgt_StackManager.ixx>
6 #include <Standard_ProgramError.hxx>
7
8 #ifdef HAVE_MALLOC_H
9 # include <malloc.h>
10 #endif
11
12 #ifdef TRACE
13 #define  SHALLOWDUMP ShallowDump(cout)
14 #else
15 #define  SHALLOWDUMP
16 #endif
17
18 //============================================================================
19 //==== There are two declaration of classes just for protections =============
20 //============================================================================
21
22 class _BaseElement {
23  public:
24   virtual void M1() =0;
25   virtual void M2() =0;
26   virtual void M3() =0;
27   virtual void M4() =0;
28   virtual void M5() =0;
29   virtual void M6() =0;
30   virtual void M7() =0;
31   virtual void M8() =0;
32   virtual void M9() =0;
33   virtual void M10()=0;
34 }; 
35
36 static class _Element: public _BaseElement 
37 {
38  public:
39   _Element() {};
40   void Msg() 
41     {Standard_ProgramError::Raise("Attempt to access to a 'deleted' object");}
42   void M1() {Msg();}
43   void M2() {Msg();}
44   void M3() {Msg();}
45   void M4() {Msg();}
46   void M5() {Msg();}
47   void M6() {Msg();}
48   void M7() {Msg();}
49   void M8() {Msg();}
50   void M9() {Msg();}
51   void M10(){Msg();}
52   
53   Standard_Address myNext;
54   
55 } *anElement = new _Element;
56
57 //============================================================================
58
59 //============================================================================
60 MMgt_StackManager::MMgt_StackManager()
61 {
62   myFreeListSize = sizeof(_Element);
63   myFreeList = (Standard_Address)calloc((int)(myFreeListSize+1),
64                                         sizeof(myFreeList));
65 }
66
67 //============================================================================
68 void MMgt_StackManager::Destructor() 
69 {
70   SHALLOWDUMP;
71
72   Purge();
73   free((char*) myFreeList);
74   myFreeListSize = 0;
75
76   SHALLOWDUMP;
77 }
78
79 //============================================================================
80 void MMgt_StackManager::ShallowDump(Standard_OStream& s) const 
81 {
82   Standard_Address aFree;
83   Standard_Integer i, NbFree;
84   
85   s << "Begin class MMgt_StackManager\n" << endl
86     << "\t... Size:" << myFreeListSize << endl;
87
88   //==== A loop for Dumping all the storage in the Free List ===========
89   for(i=sizeof(Standard_Address); i<= myFreeListSize; i++){
90     aFree = ((Standard_Address *)myFreeList)[i];
91     
92     NbFree = 0;
93     //==== A loop for deallocating all the storage with the same size =======
94     while(aFree){
95       aFree = ((_Element *)aFree)->myNext;
96       NbFree++;
97     }
98     if(NbFree) s<< "\t... ["<< i<< "]: ("<< NbFree<< ") Free Block "<< endl;
99   }
100   s << "End class MMgt_StackManager" << endl;
101 }
102
103 //============================================================================
104 MMgt_StackManager MMgt_StackManager::ShallowCopy() const
105 {
106   Standard_ProgramError::Raise
107     ("Attempt to make a ShallowCopy of a 'MMgt_StackManager'");
108   return *this;
109 }
110
111 //============================================================================
112 Standard_Address MMgt_StackManager::Allocate(const Standard_Integer aSize)
113 {
114   Standard_Address aStack;
115
116   if(aSize <= myFreeListSize && ((void* *)myFreeList)[aSize] != NULL){
117
118     //==== There is the free storage in the Free List, so we use it ==========
119     aStack = ((Standard_Address *)myFreeList)[aSize];
120     ((Standard_Address *)myFreeList)[aSize] = ((_Element *)aStack)->myNext;
121
122     //==== The storage is set to 0 ===========================================
123     memset(aStack,0,(int)aSize);
124
125   } else {
126
127     //==== There is no storage to be used, so we allocated it from "heap" ====
128     aStack = (void *)calloc((int)aSize, sizeof(char));
129   }
130   
131   return aStack;
132 }
133
134 //============================================================================
135 void MMgt_StackManager::Free(Standard_Address& aStack, 
136                              const Standard_Integer aSize)
137 {
138    //==== Only the Storage large than a 'Element' can be used ================
139    if((unsigned int ) aSize > sizeof(_Element)){
140
141      if(aSize > myFreeListSize) {
142
143        //==== If there is no storage of this size in FreeList ================
144        myFreeList=(Standard_Address)realloc((char *)myFreeList,
145                                             (int)(aSize+1)*sizeof(myFreeList));
146
147        //==== Initialize to "NULL" the new case of FreeList =================
148        for(Standard_Integer i=myFreeListSize+1; i<=aSize; i++){
149          ((Standard_Address *)myFreeList)[i] = NULL;
150        }
151
152        myFreeListSize = aSize;
153      }
154
155      //==== Recycling the storage in the Free List ===========================
156      anElement->myNext = ((Standard_Address *)myFreeList)[aSize];
157
158      memcpy((char *)aStack, (char *)anElement, sizeof(_Element));
159      ((Standard_Address *)myFreeList)[aSize] = aStack;
160    } else {
161      //==== The littles storgas will be managed by system ====================
162      free((char *) aStack);
163    }
164
165    //==== Nullify ============================================================
166    aStack = NULL;
167 }
168
169 void MMgt_StackManager::Purge()
170 {
171   Standard_Address aFree;
172   Standard_Address aOther;
173   
174   Standard_Integer i;
175   
176   //==== A loop for deallocating all the storage in the Free List ===========
177   for(i=sizeof(Standard_Address); i<= myFreeListSize; i++){
178     aFree = ((Standard_Address *)myFreeList)[i];
179     
180     //==== A loop for deallocating all the storage with the same size =======
181     while(aFree){
182       aOther = aFree;
183       aFree = ((_Element *)aFree)->myNext;
184       free((char *)aOther); 
185     }
186     
187     ((Standard_Address *)myFreeList)[i] = NULL;
188   }
189 }
190