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