ADMB Documentation  11.5.3260
 All Classes Files Functions Variables Typedefs Friends Defines
adpool.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Author: David Fournier
00005  * Copyright (c) 2008-2012 Regents of the University of California
00006  */
00012 #include <df1b2fun.h>
00013 #include <adpool.h>
00014 #include <stdint.h>
00015 #ifndef OPT_LIB
00016   #include <cassert>
00017   #include <climits>
00018 #endif
00019 //#define (_USE_VALGRIND_)
00020 
00025 int adpool::depth_check(void)
00026 {
00027   link * p=head;
00028   int depth=0;
00029   while (p)
00030   {
00031     depth++;
00032     p=p->next;
00033   }
00034   return depth;
00035 }
00036 
00037 
00038   int adpool::num_adpools=0;
00039 
00040 #if defined(__CHECK_MEMORY__)
00041 
00045 void adpool::sanity_check(void)
00046 {
00047   link * p=head;
00048   int depth=0;
00049   while (p)
00050   {
00051     depth++;
00052     if(bad(p))
00053       cerr << "Error in adpool structure" << endl;
00054     p=p->next;
00055   }
00056   cout << "Depth = " << depth << endl;
00057 }
00058 
00063 void adpool::sanity_check2(void)
00064 {
00065   link * p=head;
00066   int depth=0;
00067   while (p)
00068   {
00069     depth++;
00070     if(badaddress(p))
00071       cerr << "Error in adpool adresses" << endl;
00072     p=p->next;
00073   }
00074   cout << "Depth = " << depth << endl;
00075 }
00076 
00081 void adpool::sanity_check(void * ptr)
00082 {
00083   link * p=head;
00084   int depth=0;
00085   while (p)
00086   {
00087     depth++;
00088     if (p == ptr)
00089     {
00090       cerr << "both allocated and unallocated memory at entry "
00091            << depth << endl;
00092       break;
00093     }
00094     p=p->next;
00095   }
00096 }
00097 
00103 void adpool::write_pointers(int mmin,int mmax)
00104 {
00105   link * p=head;
00106   int index=0;
00107   while (p)
00108   {
00109     index++;
00110     if (index >=mmin && index <=mmax)
00111       cout << index << "  "  << int(p) << endl;
00112     p=p->next;
00113   }
00114 }
00115 #endif
00116 
00120 void* adpool::alloc(void)
00121 {
00122   if (!head)
00123   {
00124     grow();
00125   }
00126   link* p = head;
00127 
00128 #if defined(__CHECK_MEMORY__)
00129   if(bad(p))
00130   {
00131     cerr << "Error in adpool structure" << endl;
00132     ad_exit(1);
00133   }
00134   if (p->next)
00135   {
00136     if(bad(p->next))
00137     {
00138       cerr << "Error in adpool structure" << endl;
00139       ad_exit(1);
00140     }
00141   }
00142 #endif
00143 
00144   head = p->next;
00145   num_allocated++;
00146 
00147 #if defined(__CHECK_MEMORY__)
00148   if (p == pchecker)
00149   {
00150     cout << "trying to allocate already allocated object " << endl;
00151   }
00152 #endif
00153 
00154 #ifndef OPT_LIB
00155   assert(nvar <= SHRT_MAX);
00156 #endif
00157   ((twointsandptr*)p)->nvar=(short)nvar;
00158   ((twointsandptr*)p)->ptr=this;
00159 #if defined (INCLUDE_BLOCKSIZE)
00160   ((twointsandptr*)p)->blocksize=size;
00161 #endif
00162 
00163   return p;
00164 }
00165 
00166 #if defined(__CHECK_MEMORY__)
00167 
00170 int adpool::bad(link * p)
00171 {
00172   int flag=1;
00173   //if (!df1b2variable::adpool_counter)
00174   {
00175     //int ip=(int)p;
00176     for (int i=1;i<maxchunks;i++)
00177     {
00178       if ( p >= minaddress[i] && p <= maxaddress[i])
00179       {
00180         flag=0;
00181         break;
00182       }
00183     }
00184   }
00185   //else
00186   //{
00187   //  flag=0;
00188   //}
00189   if (flag)
00190   {
00191     cerr << "bad pool object" << endl;
00192   }
00193   return flag;
00194 }
00195 
00200 int adpool::badaddress(link * p)
00201 {
00202   int flag=1;
00203   int ip=(int)p;
00204   for (int i=0;i<=nalloc;i++)
00205   {
00206     if ( ip == pvalues[i])
00207     {
00208       flag=0;
00209       break;
00210     }
00211   }
00212   return flag;
00213 }
00214 void * pchecker=0;
00215 #endif
00216 
00221 void adpool::free(void * b)
00222 {
00223 #if defined(SAFE_ALL)
00224   twointsandptr* tmp = (twointsandptr*)(b);
00225   if (tmp->nvar != nvar)
00226   {
00227     cerr << "trying to add wrong sized memory block to adpool" << endl;
00228     ad_exit(1);
00229   }
00230 #endif
00231 
00232 #if defined (INCLUDE_BLOCKSIZE)
00233 
00234   {
00235     twointsandptr* tmp = (twointsandptr*)(b);
00236     if (tmp->blocksize != size)
00237     {
00238       cerr << "trying to add wrong sized memory block to adpool" << endl;
00239       ad_exit(1);
00240     }
00241   }
00242 #endif
00243 
00244 #if defined(__CHECK_MEMORY__)
00245    if (pchecker)
00246    {
00247      if (b == pchecker)
00248      {
00249        cout << "trying to deallocate allocated object " << endl;
00250      }
00251    }
00252 #endif
00253   //cout << "freeing " << b << endl;
00254   link * p = (link*) b;
00255   p->next = head;
00256   num_allocated--;
00257   head = p;
00258 }
00259 
00264 adpool::~adpool(void)
00265 {
00266   num_adpools--;
00267   deallocate();
00268 }
00269 
00274 adpool::adpool(const size_t sz):
00275   size(sz < sizeof(link*) ? sizeof(link*) : sz)
00276 {
00277   num_adpools++;
00278   adpool_vector_flag=0;
00279   if (!sz) size=0;
00280   last_chunk=0;
00281   head = 0;
00282   num_allocated=0;
00283   num_chunks=0;
00284 #if defined(__CHECK_MEMORY__)
00285   nalloc=0;
00286   pvalues=0;
00287   maxchunks=0;
00288 #endif
00289 }
00290 
00294 adpool::adpool()
00295 {
00296   num_adpools++;
00297   size_t i1=sizeof(twointsandptr);
00298   size_t i2=2*sizeof(double);
00299   if (i1>i2)
00300   {
00301     cout << "Error because sizeof(twointsandptr)>2*sizeof(double)" << endl;
00302     ad_exit(1);
00303   }
00304   adpool_vector_flag=0;
00305   size=0;
00306   last_chunk=0;
00307   head = 0;
00308   num_allocated=0;
00309   num_chunks=0;
00310 #if defined(__CHECK_MEMORY__)
00311   nalloc=0;
00312   pvalues=0;
00313   maxchunks=0;
00314 #endif
00315 }
00316 
00322 void adpool::set_size(const size_t sz)
00323 {
00324   if (size != sz && size != 0)
00325   {
00326     cerr << "You can not change the allocation size in mid stream\n"
00327          << " current size is " << size << " trying to change to "
00328          << sz << '\n';
00329   }
00330   size = sz;
00331 }
00332 
00337 void adpool::deallocate(void)
00338 {
00339 #if defined(__CHECK_MEMORY__)
00340   sanity_check();
00341   sanity_check2();
00342 #endif
00343   while (last_chunk)
00344   {
00345     num_chunks--;
00346     char * tmp=*(char**) last_chunk;
00347     delete [] last_chunk;
00348     last_chunk=tmp;
00349   }
00350   size=0;
00351   head=0;
00352   num_allocated=0;
00353   first=0;
00354 #if defined(__CHECK_MEMORY__)
00355   nalloc=0;
00356   delete [] pvalues;
00357   pvalues=0;
00358 #endif
00359 }
00360 /*
00361 void adpool::deallocate(void)
00362 {
00363   last_chunk=0
00364   size=0;
00365   head = 0;
00366 }
00367 */
00368 
00371 void adpool::grow(void)
00372 {
00373 #if defined(__CHECK_MEMORY__)
00374   const int pvalues_size=500000;
00375   if (!pvalues)
00376   {
00377     maxchunks=20000;
00378     nalloc=0;
00379     pvalues=new int[pvalues_size];
00380   }
00381 #endif
00382 
00383   const size_t overhead = sizeof(intptr_t);
00384   const size_t chunk_size = 16 * 65000 - overhead;
00385   if (size > 0)
00386   {
00387     nelem = chunk_size / size;
00388   }
00389   else
00390   {
00391     cerr << "error in adpool object " // << poolname
00392          << " you must set the unit size " << endl;
00393     ad_exit(1);
00394   }
00395   const size_t total_size = overhead + nelem * size;
00396   char* real_start = new char[total_size];
00397   memset(real_start, 0, total_size);
00398 
00399 #if defined(_USE_VALGRIND_)
00400    VALGRIND_MAKE_MEM_NOACCESS(realstart,chunk_size);
00401 #endif
00402 
00403   char* start = real_start + overhead;
00404   char* last = &start[(nelem - 1) * size];
00405   num_chunks++;
00406 
00407 #if defined(__CHECK_MEMORY__)
00408   if (num_chunks<maxchunks)
00409   {
00410     minaddress[num_chunks]=(real_start);
00411     maxaddress[num_chunks]=(real_start+chunk_size-1);
00412   }
00413 #endif
00414 
00415   if (last_chunk == 0)
00416   {
00417     last_chunk = real_start;
00418     *(char**)real_start = 0;
00419   }
00420   else
00421   {
00422     *(char**)real_start = last_chunk;
00423     last_chunk = real_start;
00424   }
00425 
00426 #if defined(__CHECK_MEMORY__)
00427   if (nalloc>pvalues_size-1)
00428   {
00429     cerr << "Error in check memory need to make pvalues bigger than "
00430       << pvalues_size << endl;
00431     ad_exit(1);
00432   }
00433   pvalues[nalloc++]=int(start);
00434 #endif
00435 
00436   for (char* p = start; p < last; p += size)
00437   {
00438     ((link *)p)->next = (link*)(p+size);
00439 #if defined(__CHECK_MEMORY__)
00440     pvalues[nalloc++]=int((link*)(p+size));
00441 #endif
00442   }
00443 
00444   ((link*)last)->next = 0;
00445   head = (link*)start;
00446   first = (double*)start;
00447 }
00448 
00453 void adpool::clean(void)
00454 {
00455   if (!size)
00456   {
00457     cerr << "error in adpool object " // << poolname
00458          << " you must set the unit size " << endl;
00459   }
00460   //const int overhead = 12;
00461 
00462   double *ptr=first;
00463   for (size_t i=1;i<=nelem;i++)
00464   {
00465     ptr++;
00466     for(unsigned int j=1;j<=size/sizeof(double)-2;j++) *ptr++=0.0;
00467     ptr++;
00468   }
00469 }