/home/coin/SVN-release/CoinAll-1.1.0/cppad/cppad/track_new_del.hpp

Go to the documentation of this file.
00001 # ifndef CPPAD_TRACK_NEW_DEL_INCLUDED
00002 # define CPPAD_TRACK_NEW_DEL_INCLUDED
00003 
00004 /* --------------------------------------------------------------------------
00005 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-07 Bradley M. Bell
00006 
00007 CppAD is distributed under multiple licenses. This distribution is under
00008 the terms of the 
00009                     Common Public License Version 1.0.
00010 
00011 A copy of this license is included in the COPYING file of this distribution.
00012 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
00013 -------------------------------------------------------------------------- */
00014 /*
00015 $begin TrackNewDel$$
00016 $spell
00017         cppad.hpp
00018         Cpp
00019         newptr
00020         Vec
00021         oldptr
00022         newlen
00023         ncopy
00024         const
00025 $$
00026 
00027 $section Routines That Track Use of New and Delete$$
00028 $index new, track$$
00029 $index delete, track$$
00030 $index track, new and delete$$
00031 $index memory, track$$
00032 
00033 $head Syntax$$
00034 $syntax%# include <cppad/track_new_del.hpp>
00035 %$$
00036 $syntax%%newptr% = TrackNewVec(%file%, %line%, %newlen%, %oldptr%)
00037 %$$
00038 $syntax%TrackDelVec(%file%, %line%, %oldptr%)
00039 %$$
00040 $syntax%%newptr% = TrackExtend(%file%, %line%, %newlen%, %ncopy%, %oldptr%)
00041 %$$
00042 $syntax%%count% = TrackCount(%file%, %line%)%$$
00043 
00044 
00045 $head Purpose$$
00046 These routines 
00047 aid in the use of $code new[]$$ and  $code delete[]$$
00048 during the execution of a C++ program.
00049 
00050 $head Include$$
00051 The file $code cppad/track_new_del.hpp$$ is included by 
00052 $code cppad/cppad.hpp$$
00053 but it can also be included separately with out the rest of the 
00054 CppAD include files.
00055 
00056 
00057 $head file$$
00058 The argument $italic file$$ has prototype
00059 $syntax%
00060         const char *%file%
00061 %$$
00062 It should be the source code file name 
00063 where the call to $code TrackNew$$ is located.
00064 The best way to accomplish this is the use the preprocessor symbol
00065 $code __FILE__$$ for this argument.
00066 
00067 $head line$$
00068 The argument $italic line$$ has prototype
00069 $syntax%
00070         int %line%
00071 %$$
00072 It should be the source code file line number 
00073 where the call to $code TrackNew$$ is located.
00074 The best way to accomplish this is the use the preprocessor symbol
00075 $code __LINE__$$ for this argument.
00076 
00077 $head oldptr$$
00078 The argument $italic oldptr$$ has prototype
00079 $syntax%
00080         %Type% *%oldptr%
00081 %$$
00082 This argument is used to identify the type $italic Type$$.
00083 
00084 $subhead OpenMP$$
00085 $index OpenMP, TrackNewDel$$
00086 $index TrackNewDel, OpenMP$$ 
00087 In the case of multi-threading with OpenMP,
00088 calls with the argument $italic oldptr$$ must be made with the
00089 same thread as when $italic oldptr$$ was created
00090 (except for $code TrackNewVec$$ where the value of $italic oldptr$$
00091 does not matter).
00092 
00093 
00094 $head newlen$$
00095 The argument $italic newlen$$ has prototype
00096 $syntax%
00097         size_t %newlen%
00098 %$$
00099 
00100 $head head newptr$$
00101 The return value $italic newptr$$ has prototype
00102 $syntax%
00103         %Type% *%newptr%
00104 %$$
00105 It points to the newly allocated vector of objects
00106 that were allocated using
00107 $syntax%
00108         new Type[%newlen%]
00109 %$$
00110 
00111 $head ncopy$$
00112 The argument $italic ncopy$$ has prototype
00113 $syntax%
00114         size_t %ncopy%
00115 %$$
00116 This specifies the number of elements that are copied from
00117 the old array to the new array.
00118 The value of $italic ncopy$$ 
00119 must be less than or equal $italic newlen$$.
00120 
00121 $head TrackNewVec$$
00122 $index TrackNewVec$$
00123 $index NDEBUG$$
00124 If $code NDEBUG$$ is defined, this routine only sets
00125 $syntax%
00126         %newptr% = %Type% new[%newlen%]
00127 %$$
00128 The value of $italic oldptr$$ does not matter 
00129 (except that it is used to identify $italic Type$$).
00130 If $code NDEBUG$$ is not defined, $code TrackNewVec$$ also
00131 tracks the this memory allocation.
00132 In this case, if memory cannot be allocated
00133 $xref/ErrorHandler/$$ is used to generate a message
00134 stating that there was not sufficient memory.
00135 
00136 $subhead Macro$$
00137 $index CPPAD_TRACK_NEW_VEC$$
00138 The preprocessor macro call
00139 $syntax%
00140         CPPAD_TRACK_NEW_VEC(%newlen%, %oldptr%)
00141 %$$
00142 expands to
00143 $syntax%
00144         CppAD::TrackNewVec(__FILE__, __LINE__, %newlen%, %oldptr%)
00145 %$$
00146 
00147 $subhead Deprecated$$
00148 $index  CppADTrackNewVec$$
00149 The preprocessor macro $code CppADTrackNewVec$$ is the
00150 same as $code CPPAD_TRACK_NEW_VEC$$.
00151 It has been deprecated; i.e.,
00152 it is still defined in the CppAD distribution, but it should
00153 not be used.
00154 
00155 $head TrackDelVec$$
00156 $index TrackDelVec$$
00157 This routine is used to a vector of objects 
00158 that have been allocated using $code TrackNew$$ or $code TrackExtend$$.
00159 If $code NDEBUG$$ is defined, this routine only frees memory with
00160 $syntax%
00161         delete [] %oldptr%
00162 %$$
00163 If $code NDEBUG$$ is not defined, $code TrackDelete$$ also checks that
00164 $italic oldptr$$ was allocated by $code TrackNew$$ or $code TrackExtend$$
00165 and has not yet been freed.
00166 If this is not the case,
00167 $xref/ErrorHandler/$$ is used to generate an error message.
00168 
00169 $subhead Macro$$
00170 $index CPPAD_TRACK_DEL_VEC$$
00171 The preprocessor macro call
00172 $syntax%
00173         CPPAD_TRACK_DEL_VEC(%oldptr%)
00174 %$$
00175 expands to
00176 $syntax%
00177         CppAD::TrackDelVec(__FILE__, __LINE__, %oldptr%)
00178 %$$
00179 
00180 $subhead Deprecated$$
00181 $index  CppADTrackDelVec$$
00182 The preprocessor macro $code CppADTrackDelVec$$ is the
00183 same as $code CPPAD_TRACK_DEL_VEC$$.
00184 It has been deprecated; i.e.,
00185 it is still defined in the CppAD distribution, but it should
00186 not be used.
00187 
00188 $head TrackExtend$$
00189 $index TrackExtend$$
00190 This routine is used to 
00191 allocate a new vector (using $code TrackNewVec$$),
00192 copy $italic ncopy$$ elements from the old vector to the new vector.
00193 If $italic ncopy$$ is greater than zero, $italic oldptr$$ 
00194 must have been allocated using $code TrackNewVec$$ or $code TrackExtend$$.
00195 In this case, the vector pointed to by $italic oldptr$$ 
00196 must be have at least $italic ncopy$$ elements
00197 and it will be deleted (using $code TrackDelVec$$).
00198 Note that the dependence of $code TrackExtend$$ on $code NDEBUG$$
00199 is indirectly through the routines $code TrackNewVec$$ and 
00200 $code TrackDelVec$$.
00201 
00202 $subhead Macro$$
00203 $index CPPAD_TRACK_EXTEND$$
00204 The preprocessor macro call
00205 $syntax%
00206         CPPAD_TRACK_EXTEND(%newlen%, %ncopy%, %oldptr%)
00207 %$$
00208 expands to
00209 $syntax%
00210         CppAD::TrackExtend(__FILE__, __LINE__, %newlen%, %ncopy%, %oldptr%)
00211 %$$
00212 
00213 $subhead Deprecated$$
00214 $index  CppADTrackExtend$$
00215 The preprocessor macro $code CppADTrackExtend$$ is the
00216 same as $code CPPAD_TRACK_EXTEND$$.
00217 It has been deprecated; i.e.,
00218 it is still defined in the CppAD distribution, but it should
00219 not be used.
00220 
00221 $head TrackCount$$
00222 $index TrackCount$$
00223 The return value $italic count$$ has prototype
00224 $syntax%
00225         size_t %count%
00226 %$$
00227 If $code NDEBUG$$ is defined, $italic count$$ will be zero.
00228 Otherwise, it will be
00229 the number of vectors that 
00230 have been allocated
00231 (by $code TrackNewVec$$ or $code TrackExtend$$)
00232 and not yet freed
00233 (by $code TrackDelete$$).
00234 $syntax%
00235         CppADTrackCount()
00236 %$$
00237 expands to
00238 $syntax%
00239         CppAD::TrackCount(__FILE__, __LINE__)
00240 %$$
00241 
00242 $subhead OpenMP$$
00243 $index OpenMP, TrackCount$$
00244 $index TrackCount, OpenMP$$
00245 In the case of multi-threading with OpenMP,
00246 the information for all of the threads is checked 
00247 so only one thread can be running
00248 when this routine is called.
00249 
00250 $head Example$$
00251 $children%
00252         example/track_new_del.cpp
00253 %$$
00254 The file $xref/TrackNewDel.cpp/$$
00255 contains an example and test of these functions.
00256 It returns true, if it succeeds, and false otherwise.
00257 
00258 $end
00259 ------------------------------------------------------------------------------
00260 */
00261 # include <cppad/local/cppad_assert.hpp>
00262 # include <sstream>
00263 # include <string>
00264 
00265 # ifdef _OPENMP
00266 # include <omp.h>
00267 # endif
00268 
00269 
00270 # ifndef CPPAD_NULL
00271 # define CPPAD_NULL     0
00272 # endif
00273 
00274 # ifndef CPPAD_MAX_NUM_THREADS
00275 # ifdef _OPENMP
00276 # define CPPAD_MAX_NUM_THREADS 32
00277 # else
00278 # define CPPAD_MAX_NUM_THREADS 1
00279 # endif
00280 # endif
00281 
00282 # define CPPAD_TRACK_DEBUG 0
00283 
00284 // -------------------------------------------------------------------------
00285 # define CPPAD_TRACK_NEW_VEC(newlen, oldptr) \
00286         CppAD::TrackNewVec(__FILE__, __LINE__, newlen, oldptr)
00287 
00288 # define CPPAD_TRACK_DEL_VEC(oldptr) \
00289         CppAD::TrackDelVec(__FILE__, __LINE__, oldptr)
00290 
00291 # define CPPAD_TRACK_EXTEND(newlen, ncopy, oldptr) \
00292         CppAD::TrackExtend(__FILE__, __LINE__, newlen, ncopy, oldptr)
00293 
00294 # define CppADTrackCount() \
00295         CppAD::TrackCount(__FILE__, __LINE__)
00296 // -------------------------------------------------------------------------
00297 # define CppADTrackNewVec CPPAD_TRACK_NEW_VEC
00298 # define CppADTrackDelVec CPPAD_TRACK_DEL_VEC
00299 # define CppADTrackExtend CPPAD_TRACK_EXTEND
00300 // -------------------------------------------------------------------------
00301 namespace CppAD { // Begin CppAD namespace
00302 
00303 // TrackElement ------------------------------------------------------------
00304 class TrackElement {
00305         
00306 public:
00307         std::string   file;   // corresponding file name
00308         int           line;   // corresponding line number
00309         void          *ptr;   // value returned by TrackNew
00310         TrackElement *next;   // next element in linked list
00311 
00312         // default contructor (used to initialize root)
00313         TrackElement(void)
00314         : file(""), line(0), ptr(CPPAD_NULL), next(CPPAD_NULL)
00315         { }
00316         
00317         TrackElement(const char *f, int l, void *p)
00318         : file(f), line(l), ptr(p), next(CPPAD_NULL)
00319         {       CPPAD_ASSERT_UNKNOWN( p != CPPAD_NULL);
00320         }
00321 
00322         // There is only one tracking list and it starts it here
00323         static TrackElement *root_for(size_t thread)
00324         {       static TrackElement root[CPPAD_MAX_NUM_THREADS];
00325                 CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS );
00326                 return root + thread;
00327         }
00328 
00329         // There is only one tracking list and it starts it here
00330         static TrackElement *Root(void)
00331         {
00332 # ifdef _OPENMP
00333                 size_t thread = static_cast<size_t> ( omp_get_thread_num() );
00334 # else
00335                 size_t thread = 0;
00336 # endif
00337                 CPPAD_ASSERT_KNOWN(
00338                         thread < CPPAD_MAX_NUM_THREADS,
00339                         "TrackNewDel: too many OpenMP threads are active."
00340                 );
00341                 return root_for(thread); 
00342         }
00343 
00344         // Print the linked list
00345         static void Print(size_t thread)
00346         {       using std::cout;
00347                 using std::endl;
00348                 TrackElement *E = Root();
00349                 // convert int(size_t) to avoid warning on _MSC_VER systems
00350                 cout << "Begin Track List for thread " << int(thread) << endl;
00351                 while( E->next != CPPAD_NULL )
00352                 {       E = E->next;
00353                         cout << "next = " << E->next;
00354                         cout << ", ptr  = " << E->ptr;
00355                         cout << ", line = " << E->line;
00356                         cout << ", file = " << E->file;
00357                         cout << endl;
00358                 }
00359                 cout << "End Track List for thread " << int(thread) << endl;
00360                 cout << endl;
00361         }
00362 }; 
00363 
00364 
00365 // TrackError ----------------------------------------------------------------
00366 inline void TrackError(
00367         const char *routine,
00368         const char *file,
00369         int         line,
00370         const char *msg )
00371 {
00372         std::ostringstream buf;
00373         buf << routine
00374             << ": at line "
00375             << line
00376             << " in file "
00377             << file
00378             << std::endl
00379             << msg; 
00380         std::string str = buf.str();
00381         size_t      n   = str.size();
00382         size_t i;
00383         char *message = new char[n + 1];
00384         for(i = 0; i < n; i++)
00385                 message[i] = str[i];
00386         message[n] = '\0';
00387         CPPAD_ASSERT_KNOWN( false , message);
00388 }
00389 
00390 // TrackNewVec ---------------------------------------------------------------
00391 # ifdef NDEBUG
00392 template <class Type>
00393 inline Type *TrackNewVec(
00394         const char *file, int line, size_t len, Type * /* oldptr */ )
00395 {       return (new Type[len]); 
00396 }
00397 
00398 # else
00399 
00400 template <class Type>
00401 Type *TrackNewVec(
00402         const char *file          , 
00403         int         line          , 
00404         size_t      len           ,
00405         Type       * /* oldptr */ )
00406 {
00407         // try to allocate the new memrory
00408         Type *newptr = CPPAD_NULL;
00409         try
00410         {       newptr = new Type[len];
00411         }
00412         catch(...)
00413         {       TrackError("TrackNewVec", file, line, 
00414                         "Cannot allocate sufficient memory"
00415                 );
00416         }
00417         // create tracking element
00418         void *vptr = static_cast<void *>(newptr);
00419         TrackElement *E = new TrackElement(file, line, vptr);
00420 
00421         // get the root
00422         TrackElement *root = TrackElement::Root();
00423 
00424         // put this elemenent at the front of linked list
00425         E->next    = root->next;  
00426         root->next = E;
00427 
00428         return newptr;
00429 }
00430 
00431 # endif
00432 
00433 // TrackDelVec --------------------------------------------------------------
00434 # ifdef NDEBUG
00435 template <class Type>
00436 inline void TrackDelVec(const char *file, int line, Type *oldptr)
00437 {        delete [] oldptr; 
00438 }
00439 
00440 # else
00441 
00442 template <class Type>
00443 void TrackDelVec(
00444         const char *file    ,
00445         int         line    ,
00446         Type       *oldptr  )
00447 {
00448         TrackElement        *P;
00449         TrackElement        *E;
00450 
00451         // search list for pointer
00452         P          = TrackElement::Root();
00453         E          = P->next;
00454         void *vptr = static_cast<void *>(oldptr);
00455         while(E != CPPAD_NULL && E->ptr != vptr)
00456         {       P = E;
00457                 E = E->next;
00458         }
00459 
00460         // check if pointer was not in list
00461         if( E == CPPAD_NULL || E->ptr != vptr ) TrackError(
00462                 "TrackDelVec", file, line, 
00463                 "Invalid value for the argument oldptr.\n"
00464                 "Possible linking of debug and NDEBUG compliations of CppAD."
00465         ); 
00466 
00467         // remove tracking element from list
00468         P->next = E->next;
00469 
00470         // delete allocated pointer
00471         delete [] oldptr;
00472 
00473         // delete tracking element
00474         delete E;
00475 
00476         return;
00477 }
00478 
00479 # endif
00480 
00481 // TrackExtend --------------------------------------------------------------
00482 template <class Type>
00483 Type *TrackExtend(
00484         const char *file    , 
00485         int         line    , 
00486         size_t      newlen  , 
00487         size_t      ncopy   ,
00488         Type       *oldptr  ) 
00489 {       // check size of ncopy
00490         CPPAD_ASSERT_KNOWN( 
00491                 ncopy <= newlen,
00492                 "TrackExtend: ncopy is greater than newlen."
00493         );
00494 
00495         // allocate the new memrory
00496         Type *newptr = TrackNewVec(file, line, newlen, oldptr);
00497 
00498         // copy the data
00499         size_t i = ncopy;
00500         while(i)
00501         {       --i;
00502                 newptr[i] = oldptr[i];
00503         }
00504 
00505         // delete the old vector 
00506         if( ncopy > 0 )
00507                 TrackDelVec(file, line, oldptr);
00508 
00509         return newptr;
00510 }
00511 
00512 // TrackCount --------------------------------------------------------------
00513 inline size_t TrackCount(const char *file, int line)
00514 {
00515         size_t count = 0;
00516         size_t thread;
00517         for(thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)
00518         {
00519                 TrackElement *E = TrackElement::root_for(thread);
00520 # if CPPAD_TRACK_DEBUG
00521                 if( E->next != CPPAD_NULL )
00522                         TrackElement::Print(thread);
00523 # endif
00524 
00525                 while( E->next != CPPAD_NULL ) 
00526                 {       ++count;
00527                         E = E->next;
00528                 }
00529         }
00530         return count;
00531 }
00532 // ---------------------------------------------------------------------------
00533 
00534 } // End CppAD namespace
00535 
00536 # undef CppADDebugTrack
00537 
00538 # endif

Generated on Sun Nov 14 14:06:33 2010 for Coin-All by  doxygen 1.4.7