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_