Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/SmallObj

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)2001 by Andrei Alexandrescu
00003 
00004   This file is a derivative of a file from the Loki Library written by
00005   Andrei Alexandrescu.  It was distributed by him under the terms
00006   listed below (titled Loki Original Distribution Terms).
00007   In accordance with the terms, this distribution contains the copyright
00008   notice here and the copyright notice and permission notice
00009   in supporting documentation.  The terms do *not* require
00010   redistribution under those same terms.  This code is distributed
00011   to you under the terms of the GNU General Public License (GPL) 
00012   below.  The GPL does not require you to maintain the terms of
00013   the Loki Original Distribution Terms, but you are encouraged to do so.
00014 
00015   This program/file is free software; you can redistribute it and/or modify
00016   it under the terms of the GNU General Public License as published by
00017   the Free Software Foundation; either version 2 of the License, or
00018   (at your option) any later version.
00019   
00020   This program is distributed in the hope that it will be useful,
00021   but WITHOUT ANY WARRANTY; without even the implied warranty of
00022   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023   GNU General Public License for more details. (http://www.gnu.org)
00024   
00025   You should have received a copy of the GNU General Public License
00026   along with this program; if not, write to the Free Software
00027   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028   
00029  ****************************************************************************
00030   Loki Original Distribution Terms:
00031 
00032   The Loki Library
00033   Copyright (c) 2001 by Andrei Alexandrescu
00034   This code accompanies the book:
00035   Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00036       Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00037   Permission to use, copy, modify, distribute and sell this software for any 
00038       purpose is hereby granted without fee, provided that the above copyright 
00039       notice appear in all copies and that both that copyright notice and this 
00040       permission notice appear in supporting documentation.
00041   The author or Addison-Welsey Longman make no representations about the 
00042       suitability of this software for any purpose. It is provided "as is" 
00043       without express or implied warranty.
00044  ****************************************************************************
00045 
00046   $Id: SmallObj 1029 2004-02-11 20:45:54Z jungd $
00047   $Revision: 1.1 $
00048   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00049   $Author: jungd $
00050  
00051 ****************************************************************************/
00052 
00053 // Last update: June 20, 2001
00054 
00055 #ifndef SMALLOBJ_INC_
00056 #define SMALLOBJ_INC_
00057 
00058 #include <base/Threads>
00059 #include <base/Singleton>
00060 #include <cstddef>
00061 #include <vector>
00062 
00063 #ifndef DEFAULT_CHUNK_SIZE
00064 #define DEFAULT_CHUNK_SIZE 4096
00065 #endif
00066 
00067 #ifndef MAX_SMALL_OBJECT_SIZE
00068 #define MAX_SMALL_OBJECT_SIZE 64
00069 #endif
00070 
00071 namespace base
00072 {
00073 ////////////////////////////////////////////////////////////////////////////////
00074 // class FixedAllocator
00075 // Offers services for allocating fixed-sized objects
00076 ////////////////////////////////////////////////////////////////////////////////
00077 
00078     class FixedAllocator
00079     {
00080     private:
00081         struct Chunk
00082         {
00083             void Init(std::size_t blockSize, unsigned char blocks);
00084             void* Allocate(std::size_t blockSize);
00085             void Deallocate(void* p, std::size_t blockSize);
00086             void Reset(std::size_t blockSize, unsigned char blocks);
00087             void Release();
00088             unsigned char* pData_;
00089             unsigned char
00090                 firstAvailableBlock_,
00091                 blocksAvailable_;
00092         };
00093         
00094         // Internal functions        
00095         void DoDeallocate(void* p);
00096         Chunk* VicinityFind(void* p);
00097         
00098         // Data 
00099         std::size_t blockSize_;
00100         unsigned char numBlocks_;
00101         typedef std::vector<Chunk> Chunks;
00102         Chunks chunks_;
00103         Chunk* allocChunk_;
00104         Chunk* deallocChunk_;
00105         // For ensuring proper copy semantics
00106         mutable const FixedAllocator* prev_;
00107         mutable const FixedAllocator* next_;
00108         
00109     public:
00110         // Create a FixedAllocator able to manage blocks of 'blockSize' size
00111         explicit FixedAllocator(std::size_t blockSize = 0);
00112         FixedAllocator(const FixedAllocator&);
00113         FixedAllocator& operator=(const FixedAllocator&);
00114         ~FixedAllocator();
00115         
00116         void Swap(FixedAllocator& rhs);
00117         
00118         // Allocate a memory block
00119         void* Allocate();
00120         // Deallocate a memory block previously allocated with Allocate()
00121         // (if that's not the case, the behavior is undefined)
00122         void Deallocate(void* p);
00123         // Returns the block size with which the FixedAllocator was initialized
00124         std::size_t BlockSize() const
00125         { return blockSize_; }
00126         // Comparison operator for sorting 
00127         bool operator<(std::size_t rhs) const
00128         { return BlockSize() < rhs; }
00129     };
00130     
00131 ////////////////////////////////////////////////////////////////////////////////
00132 // class SmallObjAllocator
00133 // Offers services for allocating small-sized objects
00134 ////////////////////////////////////////////////////////////////////////////////
00135 
00136     class SmallObjAllocator
00137     {
00138     public:
00139         SmallObjAllocator(
00140             std::size_t chunkSize, 
00141             std::size_t maxObjectSize);
00142     
00143         void* Allocate(std::size_t numBytes);
00144         void Deallocate(void* p, std::size_t size);
00145     
00146     private:
00147         SmallObjAllocator(const SmallObjAllocator&);
00148         SmallObjAllocator& operator=(const SmallObjAllocator&);
00149         
00150         typedef std::vector<FixedAllocator> Pool;
00151         Pool pool_;
00152         FixedAllocator* pLastAlloc_;
00153         FixedAllocator* pLastDealloc_;
00154         std::size_t chunkSize_;
00155         std::size_t maxObjectSize_;
00156     };
00157 
00158 ////////////////////////////////////////////////////////////////////////////////
00159 // class SmallObject
00160 // Base class for polymorphic small objects, offers fast
00161 //     allocations/deallocations
00162 ////////////////////////////////////////////////////////////////////////////////
00163 
00164     template
00165     <
00166         template <class> class ThreadingModel = DEFAULT_THREADING,
00167         std::size_t chunkSize = DEFAULT_CHUNK_SIZE,
00168         std::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE
00169     >
00170     class SmallObject : public ThreadingModel< 
00171         SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >
00172     {
00173         typedef ThreadingModel< SmallObject<ThreadingModel, 
00174                         chunkSize, maxSmallObjectSize> > MyThreadingModel;
00175                         
00176         struct MySmallObjAllocator : public SmallObjAllocator
00177         {
00178             MySmallObjAllocator() 
00179             : SmallObjAllocator(chunkSize, maxSmallObjectSize)
00180             {}
00181         };
00182         // The typedef below would make things much simpler, 
00183         //     but MWCW won't like it
00184         // typedef SingletonHolder<MySmallObjAllocator/*, CreateStatic, 
00185         //        DefaultLifetime, ThreadingModel*/> MyAllocator;
00186         
00187     public:
00188         static void* operator new(std::size_t size)
00189         {
00190 #if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
00191             typename MyThreadingModel::Lock lock;
00192             (void)lock; // get rid of warning
00193             
00194             return SingletonHolder<MySmallObjAllocator, CreateStatic, 
00195                 PhoenixSingleton>::Instance().Allocate(size);
00196 #else
00197             return ::operator new(size);
00198 #endif
00199         }
00200         static void operator delete(void* p, std::size_t size)
00201         {
00202 #if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
00203             typename MyThreadingModel::Lock lock;
00204             (void)lock; // get rid of warning
00205             
00206             SingletonHolder<MySmallObjAllocator, CreateStatic, 
00207                 PhoenixSingleton>::Instance().Deallocate(p, size);
00208 #else
00209             ::operator delete(p, size);
00210 #endif
00211         }
00212         virtual ~SmallObject() {}
00213     };
00214 } // namespace base
00215 
00216 ////////////////////////////////////////////////////////////////////////////////
00217 // Change log:
00218 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
00219 // Feb 25, 2002: David Jung: integrated into larger project - changed to 
00220 //                namespace base and changed header comments to reflect GPL
00221 //                distribution
00222 ////////////////////////////////////////////////////////////////////////////////
00223 
00224 #endif // SMALLOBJ_INC_

Generated on Thu Jul 29 15:56:14 2004 for OpenSim by doxygen 1.3.6