CoCoALib-0.9905 date: 23 May 2007


MemPool.H

Go to the documentation of this file.
00001 #ifndef CoCoA_MemPool_H
00002 #define CoCoA_MemPool_H
00003 
00004 //   Copyright (c)  2005,2006  John Abbott
00005 
00006 //   This file is part of the source of CoCoALib, the CoCoA Library.
00007 
00008 //   CoCoALib is free software; you can redistribute it and/or modify
00009 //   it under the terms of the GNU General Public License (version 2)
00010 //   as published by the Free Software Foundation.  A copy of the full
00011 //   licence may be found in the file COPYING in this directory.
00012 
00013 //   CoCoALib is distributed in the hope that it will be useful,
00014 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 //   GNU General Public License for more details.
00017 
00018 //   You should have received a copy of the GNU General Public License
00019 //   along with CoCoA; if not, write to the Free Software
00020 //   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 
00022 
00023 #include <cstddef>
00024 //using std::size_t;
00025 #include <memory>
00026 //using std::auto_ptr;
00027 #include <string>
00028 //using std::string;
00029 
00030 namespace CoCoA
00031 {
00032 
00033   class MemPoolFast;  // fwd decl
00034 
00035   // STILL EXPERIMENTAL: supposed to help you write exception clean code.
00036   class AutoPtrSlice
00037   {
00038   public:
00039     AutoPtrSlice(MemPoolFast* MemMgr, void* ptr);
00040     AutoPtrSlice(const AutoPtrSlice& copy);            // empties copy
00041     AutoPtrSlice& operator=(const AutoPtrSlice& rhs);  // empties rhs
00042     ~AutoPtrSlice();
00043     void* myPtr() const;
00044     void* myRelease();
00045   private:
00046     MemPoolFast* myMemMgr; // deliberately not mutable
00047     mutable void* mySlicePtr;
00048   };
00049 
00050 
00051 
00052 
00053   class loaf; // fwd decl, defined in MemPool.C
00054 
00055   /*-----------------------------------------------------------------*/
00056   /** \include MemPool.txt  */
00057   /*-----------------------------------------------------------------*/
00058   // This is the normal non-debugging version of MemPool; contrast with MemPoolDebug below.
00059   class MemPoolFast
00060   {
00061   public:
00062     enum FillNewLoaf_t {DontFillNewLoaf, FillNewLoaf}; // enum to avoid passing a bool argument in the ctor
00063   public:
00064     MemPoolFast(std::size_t sz, const std::string& name="Unnamed-MemPool", FillNewLoaf_t FillFlag = DontFillNewLoaf);
00065     ~MemPoolFast();
00066     void* alloc();
00067     void* alloc(std::size_t);
00068     void free(void*);
00069     void free(void*, std::size_t);
00070     AutoPtrSlice myAlloc(); // change name!!!
00071     bool IamOriginator(void* ptr) const;
00072     void SetVerbosityLevel(unsigned int lev);
00073     void myOutputStatus() const;
00074 
00075     typedef void** slice_t;
00076     static unsigned int ourInitialVerbosityLevel;
00077   private: // disable copy construction and assignment
00078     MemPoolFast(const MemPoolFast&);            ///< disallow copy construction -- never defined
00079     MemPoolFast& operator=(const MemPoolFast&); ///< disallow assignment -- never defined
00080 
00081 
00082   private: // member functions which are implementation details
00083     slice_t MakeNewLoaf();
00084   private: // data members
00085     const std::size_t mySliceSizeReq; ///< Size in bytes originally requested in ctor.
00086     const std::string myName;         ///< identification string, handy for debugging.
00087     const std::size_t mySliceWords;   ///< Size actually used as number of "words" (a word is a slice_t)
00088     const std::size_t mySliceBytes;   ///< Size actually used; always have mySliceBytes >= mySliceSizeReq.
00089     const bool myFillNewLoaf;         ///< if set, each new loaf is filled with copies of a known value.
00090     std::size_t mySlicesPerLoaf;      ///< approx number of slices new loaf should have (increases with each new loaf)
00091     slice_t myHeadOfFreeList;
00092     std::auto_ptr<loaf> myLoaves; // intrusive linked list of loaves
00093     unsigned int myVerbosityLevel; ///< if >=2 then a log message is printed each time a new loaf is made
00094   };
00095 
00096 
00097   inline AutoPtrSlice::AutoPtrSlice(MemPoolFast* MemMgr, void* ptr):
00098       myMemMgr(MemMgr),
00099       mySlicePtr(ptr)
00100   {}
00101 
00102 
00103   inline AutoPtrSlice::AutoPtrSlice(const AutoPtrSlice& copy):
00104       myMemMgr(copy.myMemMgr),
00105       mySlicePtr(copy.mySlicePtr)
00106   {
00107     copy.mySlicePtr = 0; // null ptr
00108   }
00109 
00110 
00111   inline AutoPtrSlice::~AutoPtrSlice()
00112   {
00113     if (mySlicePtr) myMemMgr->free(mySlicePtr);
00114   }
00115 
00116 
00117   inline void* AutoPtrSlice::myPtr() const
00118   {
00119     return mySlicePtr;
00120   }
00121 
00122 
00123   inline void* AutoPtrSlice::myRelease()
00124   {
00125     void* ans = mySlicePtr;
00126     mySlicePtr = 0; // null ptr
00127     return ans;
00128   }
00129 
00130 
00131   inline AutoPtrSlice MemPoolFast::myAlloc()
00132   {
00133     return AutoPtrSlice(this, alloc());
00134   }
00135 
00136 
00137   //---------------------------------------------------------------------------
00138   // This is the debugging version of MemPool; contrast with MemPoolFast above.
00139   class MemPoolDebug
00140   {
00141   public:
00142     MemPoolDebug(std::size_t sz, const std::string& name="Unnamed-MemPool", std::size_t debug_margin=ourDefaultMarginSize);
00143     // debug_margin is the number of words before and after each ptr
00144     // Copy ctor and assignment disabled -- see below.
00145     ~MemPoolDebug();
00146     void* alloc();
00147     void* alloc(std::size_t);
00148     void free(void*);
00149     void free(void*, std::size_t);
00150 
00151     void InterceptAlloc(std::size_t nth);
00152     void InterceptFree(std::size_t nth);
00153     void SetDebugLevel(unsigned int lev);
00154     void SetVerbosityLevel(unsigned int lev);
00155 
00156     // Globals used to control debugging level and verbosity.
00157     static unsigned int ourInitialVerbosityLevel;
00158     static unsigned int ourInitialDebugLevel;
00159     static unsigned int ourDefaultMarginSize; // size in words: 1 word = sizeof(slice_t)
00160     static double ourOutputStatusInterval; // print some info every so often
00161   private: // disable copy ctor and assignment
00162     MemPoolDebug(const MemPoolDebug&);            ///< disallow copy construction -- never defined
00163     MemPoolDebug& operator=(const MemPoolDebug&); ///< disallow assignment -- never defined
00164 
00165   private: // data members
00166     typedef MemPoolFast::slice_t slice_t;
00167     static const long AliveMark = ~0xbadc0c0a;
00168     long myAliveOrDead;         ///< Heuristic trick to recognise destroyed MemPools when debugging.
00169 
00170     std::string myName;         ///< Identifier useful during debugging.
00171     std::size_t mySliceSizeReq; ///< Size in bytes originally requested in ctor.
00172     std::size_t myMarginWords;  ///< number of margin words before and after each block
00173     std::size_t mySliceWords;   ///< Size of each slice in words; 1 word = sizeof(slice_t).
00174     std::size_t mySliceBytes;   ///< Size actually used; always have mySliceBytes >= mySliceSizeReq.
00175     MemPoolFast myMemMgr;       ///< myMemMgr actually manages the alloc/free requests
00176     slice_t myHeadOfUsedList;   ///< Used only in the highest debug level
00177 
00178     unsigned int myDebugLevel;  ///< debug level should be one of 0, 1, or 2 (>2 is same as 2)
00179     unsigned int myVerbosityLevel; ///< verbosity level should be one of 0, 1, 2 or 3 (>3 is same as 3)
00180     std::size_t myAllocCount;
00181     std::size_t myAllocWatchPoint;
00182     std::size_t myFreeCount;
00183     std::size_t myFreeWatchPoint;
00184     std::size_t myInUseCount;
00185     std::size_t myInUseMax;
00186     double myNextOutputStatusTime;
00187   private: // implementation details.
00188     static std::size_t ourCheckCtorSizeArg(std::size_t sz);
00189     void myAliveCheck();
00190 
00191     void AllocMark(slice_t p);
00192     void FreeMark(slice_t p);
00193 
00194     void FullOverwriteFreeCheck() const;
00195     void OverwriteErrorMesg(slice_t, void*) const;
00196     void OverwriteFreeCheck(slice_t) const;
00197     bool FreeError(void* ptr) const;
00198     void FreeErrorMesg(void* ptr, const std::string& reason) const;
00199     bool AlreadyFreed(void* ptr) const;
00200     bool WrittenOutOfRange(void* ptr) const;
00201 
00202     void PrintSlice(void* ptr) const;
00203 
00204     void DtorErrorMesg() const;
00205     void PrintStats() const;
00206     void AllocMesg(void* ptr) const;
00207     void AllocWrongSizeMesg(std::size_t sz, void* ptr) const;
00208     void FreeMesg(void* ptr) const;
00209     void FreeWrongSizeMesg(std::size_t sz, void* ptr) const;
00210     void FreeZeroPtrMesg() const;
00211     void intercepted() const;
00212   };
00213 
00214 
00215 /////////////////////////////////////////////////////////////////////////////
00216 // Define the type MemPool according to the setting of CoCoA_MEMPOOL_DEBUG.
00217 
00218 #if defined(CoCoA_MEMPOOL_DEBUG)
00219   typedef MemPoolDebug MemPool;
00220 #else
00221   typedef MemPoolFast MemPool;
00222 #endif
00223 
00224 } // end of namespace CoCoA
00225 
00226 
00227 
00228 // RCS Header/Log in the next few lines
00229 // $Header: /Volumes/Home/cocoa/cvs-repository/CoCoALib-0.99/include/CoCoA/MemPool.H,v 1.1.1.1 2007/03/09 15:16:11 abbott Exp $
00230 // $Log: MemPool.H,v $
00231 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
00232 // Imported files
00233 //
00234 // Revision 1.3  2006/12/06 17:14:12  cocoa
00235 // -- removed #include "config.H"
00236 //
00237 // Revision 1.2  2006/10/06 14:04:15  cocoa
00238 // Corrected position of #ifndef in header files.
00239 // Separated CoCoA_ASSERT into assert.H from config.H;
00240 // many minor consequential changes (have to #include assert.H).
00241 // A little tidying of #include directives (esp. in Max's code).
00242 //
00243 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
00244 // Imported files
00245 //
00246 // Revision 1.7  2006/05/15 16:28:49  cocoa
00247 // Fixed bug which appeared only when there was a double free.
00248 //
00249 // Revision 1.6  2006/04/27 13:54:19  cocoa
00250 // Improved MemPools with an experimental way of handling raw memory in an
00251 // exception clean manner.
00252 //
00253 // Revision 1.5  2006/04/11 16:34:29  cocoa
00254 // Completed overhaul of MemPool (incl documentation).
00255 // Modified GMPAllocator so that you can specify the slice size
00256 // in the ctor -- useful for experimentation.
00257 //
00258 // Revision 1.4  2006/04/07 16:44:52  cocoa
00259 // Considerably updated MemPool design -- it works, and I'm about to test
00260 // its efficiency against the old one.
00261 //
00262 // Revision 1.3  2006/03/31 13:41:00  cocoa
00263 // Temporary check in with partially updated MemPool code.
00264 //
00265 // Revision 1.2  2006/03/12 21:28:34  cocoa
00266 // Major check in after many changes
00267 //
00268 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
00269 // Imported files
00270 //
00271 // Revision 1.1.1.1  2005/05/03 15:47:30  cocoa
00272 // Imported files
00273 //
00274 // Revision 1.3  2005/04/19 14:06:04  cocoa
00275 // Added GPL and GFDL licence stuff.
00276 //
00277 // Revision 1.2  2005/02/11 14:15:20  cocoa
00278 // New style ring elements and references to ring elements;
00279 // I hope I have finally got it right!
00280 //
00281 // Revision 1.1.1.1  2005/01/27 15:12:13  cocoa
00282 // Imported files
00283 //
00284 // Revision 1.5  2004/11/19 15:14:09  cocoa
00285 // (a) Added new check to MemPool so that it can signal an
00286 //     error if one tries to use a MemPool after it has been
00287 //     destroyed.
00288 // (b) Improved makefile in TEST/ so that it checks output,
00289 //     and prints useful messages if the test fails.
00290 // (c) Tidied ring.txt a bit (still more to do).
00291 //
00292 // Revision 1.4  2004/11/08 14:03:32  cocoa
00293 // -- small changes for doxygen support
00294 //
00295 // Revision 1.3  2004/11/04 18:49:03  cocoa
00296 // (1) MemPool code cleaned up; now adheres better to the coding
00297 //     conventions.
00298 // (2) Log messages printed by MemPool (in debugging mode) are
00299 //     more uniform.
00300 //
00301 // Revision 1.2  2004/01/28 15:17:58  cocoa
00302 // Minor tidying: better indentation, cleaner code for non-debugging case.
00303 // [backed off an abortive attempt to protect against mixing code compiled
00304 // with and without CoCoA_MEMPOOL_DEBUG]
00305 //
00306 // Revision 1.1.1.1  2003/09/24 12:55:43  cocoa
00307 // Imported files
00308 //
00309 // Revision 1.8  2003/06/23 16:19:47  abbott
00310 // Minor cleaning prior to public release.
00311 //
00312 // Revision 1.7  2003/05/08 08:54:28  abbott
00313 // Minor cleaning: replaced size_t by std::size_t.
00314 // (apparently these changes were made in Nov 2002, but never checked in).
00315 //
00316 // Revision 1.6  2002/10/25 12:57:08  abbott
00317 // Added new alloc/free functions which do not require a size parameter;
00318 // the size defaults to the "natural" size for the MemPool.
00319 //
00320 // Removed the member MEMPOOL_ALLOCATED_WORD_INSIDE from the debugging
00321 // version since now different values are used for different slices.
00322 //
00323 // Revision 1.5  2002/03/05 17:30:42  abbott
00324 // Added two new debugging functions: InterceptAlloc and InterceptFree
00325 // which allow one easily to intercept the nth call to alloc/free
00326 // using a debugger (see details in the documentation).  To implement
00327 // this I added two new data fields to MemPool (in the debug case).
00328 //
00329 // Added a new field containing the number of loaves created by each
00330 // MemPool object: this is used to determine the growth of the size
00331 // of each loaf (doubles every second time).
00332 //
00333 // Revision 1.4  2002/02/07 11:47:43  abbott
00334 // Corrected two member function declarations, and added another which
00335 // was missing.
00336 //
00337 // Revision 1.3  2001/11/28 21:31:17  abbott
00338 // Radical reorganization of the code:
00339 //  * the separation into two types of file MemPool* and MemPool_DEBUG*
00340 //    has been eliminated; everything is now in MemPool.*
00341 //  * compatible with gcc-3.0.2 regarding use of namespace std;
00342 //  * many names changed (in accordance with the new coding conventions,
00343 //    and for better comprehensibility);
00344 //  * new more powerful checks added (e.g. write to a freed block),
00345 //    and more levels of debugging supported;
00346 //  * improved error messages, and progress messages.
00347 //
00348 // Revision 1.2  2001/11/16 19:25:02  bigatti
00349 // added:  std::
00350 // for compatibility with gcc-3
00351 //
00352 // Revision 1.1  2001/10/04 14:54:28  abbott
00353 // Initial revision
00354 //
00355 
00356 #endif

Generated on Wed May 23 13:45:23 2007 for CoCoALib by  doxygen 1.4.6