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