SmallObj.h

  1 ////////////////////////////////////////////////////////////////////////////////
  2 // The Loki Library
  3 // Copyright (c) 2001 by Andrei Alexandrescu
  4 // This code accompanies the book:
  5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
  6 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
  7 // Permission to use, copy, modify, distribute and sell this software for any 
  8 //     purpose is hereby granted without fee, provided that the above copyright 
  9 //     notice appear in all copies and that both that copyright notice and this 
 10 //     permission notice appear in supporting documentation.
 11 // The author or Addison-Welsey Longman make no representations about the 
 12 //     suitability of this software for any purpose. It is provided "as is" 
 13 //     without express or implied warranty.
 14 ////////////////////////////////////////////////////////////////////////////////
 15 
 16 // Last update: June 20, 2001
 17 
 18 #ifndef SMALLOBJ_INC_
 19 #define SMALLOBJ_INC_
 20 
 21 #include "Threads.h"
 22 #include "Singleton.h"
 23 #include <cstddef>
 24 #include <vector>
 25 
 26 #ifndef DEFAULT_CHUNK_SIZE
 27 #define DEFAULT_CHUNK_SIZE 4096
 28 #endif
 29 
 30 #ifndef MAX_SMALL_OBJECT_SIZE
 31 #define MAX_SMALL_OBJECT_SIZE 64
 32 #endif
 33 
 34 namespace Loki
 35 {
 36 ////////////////////////////////////////////////////////////////////////////////
 37 // class FixedAllocator
 38 // Offers services for allocating fixed-sized objects
 39 ////////////////////////////////////////////////////////////////////////////////
 40 
 41     class FixedAllocator
 42     {
 43     private:
 44         struct Chunk
 45         {
 46             void Init(std::size_t blockSize, unsigned char blocks);
 47             void* Allocate(std::size_t blockSize);
 48             void Deallocate(void* p, std::size_t blockSize);
 49             void Reset(std::size_t blockSize, unsigned char blocks);
 50             void Release();
 51             unsigned char* pData_;
 52             unsigned char
 53                 firstAvailableBlock_,
 54                 blocksAvailable_;
 55         };
 56         
 57         // Internal functions        
 58         void DoDeallocate(void* p);
 59         Chunk* VicinityFind(void* p);
 60         
 61         // Data 
 62         std::size_t blockSize_;
 63         unsigned char numBlocks_;
 64         typedef std::vector<Chunk> Chunks;
 65         Chunks chunks_;
 66         Chunk* allocChunk_;
 67         Chunk* deallocChunk_;
 68         // For ensuring proper copy semantics
 69         mutable const FixedAllocator* prev_;
 70         mutable const FixedAllocator* next_;
 71         
 72     public:
 73         // Create a FixedAllocator able to manage blocks of 'blockSize' size
 74         explicit FixedAllocator(std::size_t blockSize = 0);
 75         FixedAllocator(const FixedAllocator&);
 76         FixedAllocator& operator=(const FixedAllocator&);
 77         ~FixedAllocator();
 78         
 79         void Swap(FixedAllocator& rhs);
 80         
 81         // Allocate a memory block
 82         void* Allocate();
 83         // Deallocate a memory block previously allocated with Allocate()
 84         // (if that's not the case, the behavior is undefined)
 85         void Deallocate(void* p);
 86         // Returns the block size with which the FixedAllocator was initialized
 87         std::size_t BlockSize() const
 88         { return blockSize_; }
 89         // Comparison operator for sorting 
 90         bool operator<(std::size_t rhs) const
 91         { return BlockSize() < rhs; }
 92     };
 93     
 94 ////////////////////////////////////////////////////////////////////////////////
 95 // class SmallObjAllocator
 96 // Offers services for allocating small-sized objects
 97 ////////////////////////////////////////////////////////////////////////////////
 98 
 99     class SmallObjAllocator
100     {
101     public:
102         SmallObjAllocator(
103             std::size_t chunkSize, 
104             std::size_t maxObjectSize);
105     
106         void* Allocate(std::size_t numBytes);
107         void Deallocate(void* p, std::size_t size);
108     
109     private:
110         SmallObjAllocator(const SmallObjAllocator&);
111         SmallObjAllocator& operator=(const SmallObjAllocator&);
112         
113         typedef std::vector<FixedAllocator> Pool;
114         Pool pool_;
115         FixedAllocator* pLastAlloc_;
116         FixedAllocator* pLastDealloc_;
117         std::size_t chunkSize_;
118         std::size_t maxObjectSize_;
119     };
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 // class SmallObject
123 // Base class for polymorphic small objects, offers fast
124 //     allocations/deallocations
125 ////////////////////////////////////////////////////////////////////////////////
126 
127     template
128     <
129         template <class> class ThreadingModel = DEFAULT_THREADING,
130         std::size_t chunkSize = DEFAULT_CHUNK_SIZE,
131         std::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE
132     >
133     class SmallObject : public ThreadingModel< 
134         SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >
135     {
136         typedef ThreadingModel< SmallObject<ThreadingModel, 
137                 chunkSize, maxSmallObjectSize> > MyThreadingModel;
138                 
139         struct MySmallObjAllocator : public SmallObjAllocator
140         {
141             MySmallObjAllocator() 
142             : SmallObjAllocator(chunkSize, maxSmallObjectSize)
143             {}
144         };
145         // The typedef below would make things much simpler, 
146         //     but MWCW won't like it
147         // typedef SingletonHolder<MySmallObjAllocator/*, CreateStatic, 
148         //        DefaultLifetime, ThreadingModel*/> MyAllocator;
149         
150     public:
151         static void* operator new(std::size_t size)
152         {
153 #if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
154             typename MyThreadingModel::Lock lock;
155             (void)lock; // get rid of warning
156             
157             return SingletonHolder<MySmallObjAllocator, CreateStatic, 
158                 PhoenixSingleton>::Instance().Allocate(size);
159 #else
160             return ::operator new(size);
161 #endif
162         }
163         static void operator delete(void* p, std::size_t size)
164         {
165 #if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
166             typename MyThreadingModel::Lock lock;
167             (void)lock; // get rid of warning
168             
169             SingletonHolder<MySmallObjAllocator, CreateStatic, 
170                 PhoenixSingleton>::Instance().Deallocate(p, size);
171 #else
172             ::operator delete(p, size);
173 #endif
174         }
175         virtual ~SmallObject() {}
176     };
177 } // namespace Loki
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 // Change log:
181 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
182 ////////////////////////////////////////////////////////////////////////////////
183 
184 #endif // SMALLOBJ_INC_
posted @ 2012-10-31 15:21  crazylhf  阅读(137)  评论(0)    收藏  举报