1 /// \file
2
3 // -*- Mode : c++ -*-
4 //
5 // SUMMARY :
6 // USAGE :
7 // ORG :
8 // AUTHOR : Frederic Hecht
9 // E-MAIL : hecht@ann.jussieu.fr
10 //
11
12 /*
13
14 This file is part of Freefem++
15
16 Freefem++ is free software; you can redistribute it and/or modify
17 it under the terms of the GNU Lesser General Public License as published by
18 the Free Software Foundation; either version 2.1 of the License, or
19 (at your option) any later version.
20
21 Freefem++ is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU Lesser General Public License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with Freefem++; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30 //-----------------------------------
31 // to manage the freefem stack
32 #ifndef FFSTACK_HPP__
33 #define FFSTACK_HPP__
34
35 #include "throwassert.hpp"
36
37 // in the stack we save all the variable
38 // a adresse 0 we have the MeshPointStack to defineP,N, ....
39 // a adresse sizeof(void *)
40 //
41 //
42 // Offset in (void *)
43 const int MeshPointStackOffset =0;
44 const int ParamPtrOffset = 1;
45 const int ElemMatPtrOffset = 2;
46 const int ExprPtrs = 4;
47 const int NbPtrs = 5;
48
49
50
51 const int BeginOffset = 6;
52 // 0 : MeshPoint pointeur
53 // 1 : ParamPtrOffset
54 // 2 : Truc les matrice elementaire
55
56 #define NEWFFSTACKxxx
57
58 #ifndef NEWFFSTACK
59 typedef void StackType;
60
61 /// <<Stack>>
62 typedef void *Stack;
63
64
65 const Stack NullStack=0;
66 //typedef StackType& Stack;
pvoid2Stack(void * pv)67 inline Stack pvoid2Stack(void * pv) { return pv;}
68
69 template<class T>
Stack_offset(Stack stack,size_t offset)70 T * Stack_offset (Stack stack,size_t offset)
71 { //cout << "Stack_offset" << stack << " " << offset << endl;
72 return (T *) (void *) (((char *) stack)+offset);}
73
74 // <<Stack_Ptr>>
75 template<class T>
Stack_Ptr(Stack stack,size_t offset)76 T * & Stack_Ptr (Stack stack,size_t offset)
77 {return (T * &) (((void **) stack)[offset]);}
78
79 void ShowType(ostream & f);
80
81
82 struct VOIDPtrType {
83 virtual ~VOIDPtrType();
84 };
85
86 template<class T>
87 struct PtrType: public VOIDPtrType {
88 T * p;
PtrTypePtrType89 PtrType(T* pp):p(pp) {}
~PtrTypePtrType90 ~PtrType() {delete p;}
91 };
92
93 template<class T>
94 struct PtrArrayType: public VOIDPtrType {
95 T * p;
PtrArrayTypePtrArrayType96 PtrArrayType(T* pp):p(pp) {}
PtrArrayTypePtrArrayType97 PtrArrayType() {delete [] p;}
98 };
99
100
101 #else
102
103 struct StackType;
104
105 //typedef void *Stack;
106
107 /// Stack used by CListOfInst::eval()
108 typedef StackType & Stack;
109
110 struct StackType {
111 size_t lg;
112 char * stack;
113 char * MeshPointStack;
operator char*StackType114 operator char *() { return stack;}
operator void*StackType115 operator void *() { return stack;}
operator long*StackType116 operator long *() { return (long *)(void *)stack;}
operator void**StackType117 operator void **() {return (void **) (void *) stack;}
operator StackType*StackType118 operator StackType *() { return this;}
119 template<class T>
OffsetStackType120 T * Offset(size_t offset){ return (T*) (void*) (stack+offset);}
121 template<class T>
ptrStackType122 T *& ptr(size_t offset){ return (T* &) ((void**) (void *) stack)[offset];}
StackTypeStackType123 StackType(size_t ll) :lg(ll),stack(new char[ll]),MeshPointStack(new char[1000])
124 {
125 long * p= ptr<long>(0);
126 long l4=lg/sizeof(long);
127 for (int i = 0;i< l4;i++) p[i]=0;
128
129 ptr<char>(MeshPointStackOffset)=MeshPointStack;
130 }
cleanStackType131 void clean() { delete []stack; delete [] MeshPointStack; }
132 };
133
pvoid2Stack(void * pv)134 inline Stack pvoid2Stack(void * pv) { return *static_cast<StackType *>(pv) ;}
135 static StackType * NullStackPtr= 0;
136 static StackType & NullStack(*NullStackPtr);
137 //typedef StackType& Stack;
138
139
140 template<class T>
Stack_offset(Stack stack,size_t offset)141 T * Stack_offset (Stack stack,size_t offset)
142 {return stack.Offset<T>(offset);}
143
144 template<class T>
Stack_Ptr(Stack stack,size_t offset)145 T * & Stack_Ptr (Stack stack,size_t offset)
146 {return (T * &) (((void **) (void *) stack.stack)[offset]);}
147
148 void ShowType(ostream & f);
149
150
151 struct VOIDPtrType {
152 virtual ~VOIDPtrType();
153 };
154
155 template<class T>
156 struct PtrType: public VOIDPtrType {
157 T * p;
PtrTypePtrType158 PtrType(T* pp):p(pp) {}
~PtrTypePtrType159 ~PtrType() {delete p;}
160 };
161
162 template<class T>
163 struct PtrArrayType: public VOIDPtrType {
164 T * p;
PtrArrayTypePtrArrayType165 PtrArrayType(T* pp):p(pp) {}
PtrArrayTypePtrArrayType166 PtrArrayType() {delete [] p;}
167 };
168
169
170
171 #endif
172 //------------------------------------
173
174 // Add FH mars 2006
175 // clean pointeur ceated by the language
176 // ----
177 struct BaseNewInStack {
~BaseNewInStackBaseNewInStack178 virtual ~BaseNewInStack() {};
179 };
180
181 struct BaseNewInStack;
182 struct StackOfPtr2Free;
183
184 // <<WhereStackOfPtr2Free>> [[Stack_Ptr]] [[StackOfPtr2Free]] [[ExprPtrs]]
WhereStackOfPtr2Free(Stack s)185 inline StackOfPtr2Free * & WhereStackOfPtr2Free(Stack s) { return Stack_Ptr<StackOfPtr2Free>(s,ExprPtrs) ;} // fait
186
187 // <<StackOfPtr2Free>>
188 struct StackOfPtr2Free {
189 typedef vector<BaseNewInStack *>::iterator iterator;
190 typedef vector<BaseNewInStack *>::reverse_iterator reverse_iterator;
191 StackOfPtr2Free ** where; // where is store the ptr to the stack
192 StackOfPtr2Free *prev; // previous stack
193
194 vector<BaseNewInStack *> stackptr;
195 static const int sizeofmemory4tmp=1024;
196 int topmemory4tmp;
197 char *memory4tmp ; //
addStackOfPtr2Free198 void add(BaseNewInStack *p) {
199 // cout << "\n\t\t ### ptr/lg add " << p << " at " << stackptr.size() << " \n";
200 stackptr.push_back(p);}
201
202 public:
StackOfPtr2FreeStackOfPtr2Free203 StackOfPtr2Free(Stack s):
204 where(&WhereStackOfPtr2Free(s)),
205 prev(*where),
206 topmemory4tmp(0), // add FH oct 2008 of tmp allocation clean after each instruction
207 memory4tmp(new char[sizeofmemory4tmp]) // add FH oct 2008 of tmp allocation clean after each instruction
208 {
209 stackptr.reserve(20);
210 if(prev) Add2StackOfPtr2Free(s,this);
211 }
sizeStackOfPtr2Free212 size_t size() const {return stackptr.size();} // Add FH dec 2017
cleanStackOfPtr2Free213 bool clean(int ssize=0)
214 {
215 topmemory4tmp=0;// clean the tmp allocation
216 bool ret= !stackptr.empty();
217 if(ret)
218 {
219
220 if(stackptr.size()>=20 && verbosity>2)
221 // FFCS: nothing on following line for tests/compare
222 cout << "\n\t\t ### big?? ptr/lg clean " << stackptr.size() << " ptr's\n";
223 reverse_iterator re= stackptr.rend()-ssize;
224 for (reverse_iterator i=stackptr.rbegin(); i != re;++i)
225 {
226
227 delete (* (i) );
228 if(verbosity>400) cout << "StackOfPtr2Free: clean " << (* (i) ) << " " << endl;
229 }
230 stackptr.resize(ssize);// clean the
231
232 }
233 return ret;
234 }
allocStackOfPtr2Free235 void * alloc(int lg)
236 {
237 int lg8=lg%8;
238 if(lg8) lg += 8-lg8;
239 if(topmemory4tmp + lg>= sizeofmemory4tmp) {
240 ErrorExec(" Fatal Error: too much temporary alloction, your expression is too long, or a bug in ff++, FH; april,2015",1);
241 ffassert(0);}
242 void * p=static_cast<void*> (memory4tmp+topmemory4tmp);// correct FH Oct 2009
243 topmemory4tmp+= lg;
244 return p;
245 }
~StackOfPtr2FreeStackOfPtr2Free246 ~StackOfPtr2Free() {clean();delete [] memory4tmp; *where=prev;} // restore the previous stack
247 private:// no copy ....
248 StackOfPtr2Free(const StackOfPtr2Free&);
249 void operator =(const StackOfPtr2Free&);
250
251 template<class T>
252 friend T * NewTmp(Stack s);
253 template<class T>
254 friend T * Add2StackOfPtr2Free(Stack s,T * p);
255
256 };
257
258
NewAllocTmp(Stack s,size_t l)259 inline void * NewAllocTmp(Stack s,size_t l)
260 {
261 return WhereStackOfPtr2Free(s)->alloc(l);
262 }
263
264 template<class T>
265 struct NewInStack: public BaseNewInStack {
266 T * p;
267 bool array;
~NewInStackNewInStack268 ~NewInStack() {
269 // cout << "~NewInStack " << typeid(T).name() << " " << p << " array " << array << " " << this << "\n";
270 if(p)
271 delete p;}
272 private:
NewInStackNewInStack273 NewInStack(T * pp,bool aa=false) : p(pp),array(aa) {
274 // cout << "NewInStack " << typeid(T).name() << " " << p << " array " << aa << " " << this << "\n";
275 }
276
277
278 template<class TT>
279 friend TT * Add2StackOfPtr2FreeA(Stack s,TT * p);
280 template<class TT>
281 friend TT * Add2StackOfPtr2Free(Stack s,TT * p);
282
283 };
284
285 extern void freestring(const string *);
286
287 template<>
288 struct NewInStack<string> : public BaseNewInStack {
289 typedef string T;
290 T * p;
291 bool array;
~NewInStackNewInStack292 ~NewInStack() {
293 // cout << "~NewInStack " << typeid(T).name() << " " << p << " array " << array << " " << this << "\n";
294 if(p)
295 freestring(p);}
296 private:
NewInStackNewInStack297 NewInStack(T * pp,bool aa=false) : p(pp),array(aa) {
298 // cout << "NewInStack " << typeid(T).name() << " " << p << " array " << aa << " " << this << "\n";
299 }
300
301
302 template<class TT>
303 friend TT * Add2StackOfPtr2FreeA(Stack s,TT * p);
304 template<class TT>
305 friend TT * Add2StackOfPtr2Free(Stack s,TT * p);
306
307 };
308 // ajout of 2 class NewRefCountInStack and NewArrayInStack
309 // for clean of meshes
310
311 template<class T>
312 struct NewRefCountInStack: public BaseNewInStack {
313 T * p;
314 bool array;
~NewRefCountInStackNewRefCountInStack315 ~NewRefCountInStack() {
316 // cout << "~NewInStack " << typeid(T).name() << " " << p << " array " << array << " " << this << "\n";
317 if(p) p->destroy();}
318 private:
NewRefCountInStackNewRefCountInStack319 NewRefCountInStack(T * pp,bool aa=false) : p(pp),array(aa) {
320 // cout << "NewInStack " << typeid(T).name() << " " << p << " array " << aa << " " << this << "\n";
321 }
322
323 template<class TT>
324 friend TT * Add2StackOfPtr2FreeRC(Stack s,TT * p);
325
326 };
327
328 template<class T>
329 struct NewArrayInStack: public BaseNewInStack {
330 T * p;
331 bool array;
~NewArrayInStackNewArrayInStack332 ~NewArrayInStack() {
333 // cout << "~NewInStack " << typeid(T).name() << " " << p << " array " << array << " " << this << "\n";
334 if(p) delete [] p;
335 }
336 private:
NewArrayInStackNewArrayInStack337 NewArrayInStack(T * pp,bool aa=false) : p(pp),array(aa) {
338 // cout << "NewInStack " << typeid(T).name() << " " << p << " array " << aa << " " << this << "\n";
339 }
340
341
342 template<class TT>
343 friend TT * Add2StackOfPtr2FreeA(Stack s,TT * p);
344 template<class TT>
345 friend TT * Add2StackOfPtr2Free(Stack s,TT * p);
346
347 };
348
349 template<class T>
Add2StackOfPtr2FreeRC(Stack s,T * p)350 T * Add2StackOfPtr2FreeRC(Stack s,T * p)
351 {
352 if(p)
353 WhereStackOfPtr2Free(s)->add(new NewRefCountInStack<T>(p));
354 return p;
355 }
356
357 template<class T>
Add2StackOfPtr2Free(Stack s,T * p)358 T * Add2StackOfPtr2Free(Stack s,T * p)
359 {
360 if(p)
361 WhereStackOfPtr2Free(s)->add(new NewInStack<T>(p));
362 return p;
363 }
364 template<class T>
Add2StackOfPtr2FreeA(Stack s,T * p)365 T * Add2StackOfPtr2FreeA(Stack s,T * p)
366 {
367 if(p)
368 WhereStackOfPtr2Free(s)->add(new NewArrayInStack<T>(p));
369 return p;
370 }
371 // fin modif gestion of allocation of Ptr in Language
372 // ---------------------------------------------------
373 #ifndef NEWFFSTACK
374 extern void InitMeshPoint(void *p);
375 /// <<newStack>>
newStack(size_t l)376 inline Stack newStack(size_t l)
377 {
378 char * mps;
379 Stack thestack = new char[l];
380 for (size_t i = 0;i< l/sizeof(long);i++) ((long*) thestack)[i]=0;
381 ((char **) thestack)[MeshPointStackOffset] = mps = new char [1000];
382 for(int i=0;i<1000;++i) mps[i]=0;
383 // unset x,y,z
384 InitMeshPoint(mps);
385 // [[WhereStackOfPtr2Free]] [[StackOfPtr2Free]]
386 WhereStackOfPtr2Free(thestack)=new StackOfPtr2Free(thestack);
387
388 return thestack;
389 // return *new StackType(l);}
390 }
391
deleteStack(Stack s)392 inline void deleteStack(Stack s)
393 {
394 delete WhereStackOfPtr2Free(s); // add gestion of the Ptr
395 delete [] (((char **) s)[MeshPointStackOffset]);
396 delete [] (char *) s;
397 // s.clean();
398 }
399 #else
400 // a faire ....
401
402 /// Called to create a new #Stack used to evaluate a FreeFem++ script in CListOfInst::eval()
newStack(size_t l)403 inline Stack newStack(size_t l)
404 {
405 /* Stack thestack = new char[l];
406 for (int i = 0;i< l/sizeof(long);i++) ((long*) thestack)[i]=0;
407 ((char **) thestack)[MeshPointStackOffset] = new char [1000];
408
409 return thestack;*/
410 return *new StackType(l);
411 }
412
413
deleteStack(Stack s)414 inline void deleteStack(Stack s)
415 {
416 // delete [] (((char **) s)[MeshPointStackOffset]);
417 // delete [] (char *) s;
418 s.clean();
419 }
420 #endif
421 #endif
422