00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __PION_PIONPOOLALLOCATOR_HEADER__
00011 #define __PION_PIONPOOLALLOCATOR_HEADER__
00012
00013 #include <cstdlib>
00014 #include <boost/array.hpp>
00015 #include <boost/scoped_ptr.hpp>
00016 #include <boost/static_assert.hpp>
00017 #include <boost/noncopyable.hpp>
00018 #include <boost/thread/mutex.hpp>
00019 #include <boost/pool/pool.hpp>
00020 #include <pion/PionConfig.hpp>
00021 #include <pion/PionException.hpp>
00022
00023 #if defined(PION_HAVE_MALLOC_TRIM)
00024 #include <malloc.h>
00025 #endif
00026
00028 #if defined(PION_HAVE_LOCKFREE)
00029 #ifdef _MSC_VER
00030 #pragma warning(push)
00031 #pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)
00032 #endif
00033 #include <boost/lockfree/detail/tagged_ptr.hpp>
00034 #ifdef _MSC_VER
00035 #pragma warning(pop)
00036 #endif
00037 #include <boost/lockfree/atomic_int.hpp>
00038 #endif
00039
00040
00041 namespace pion {
00042
00043
00051 template <std::size_t MinSize = 16, std::size_t MaxSize = 256>
00052 class PionPoolAllocator
00053 : private boost::noncopyable
00054 {
00055 public:
00056
00058 virtual ~PionPoolAllocator()
00059 {}
00060
00062 PionPoolAllocator(void)
00063 {
00064 for (std::size_t n = 0; n < NumberOfAllocs; ++n) {
00065 m_pools[n].reset(new FixedSizeAlloc((n+1) * MinSize));
00066 }
00067 }
00068
00076 inline void *malloc(std::size_t n)
00077 {
00078
00079 if (n > MaxSize)
00080 return ::malloc(n);
00081 FixedSizeAlloc *pool_ptr = getPool(n);
00082
00083 #if defined(PION_HAVE_LOCKFREE)
00084 while (true) {
00085
00086 FreeListPtr old_free_ptr(pool_ptr->m_free_ptr);
00087 if (! old_free_ptr)
00088 break;
00089
00090
00091 if (pool_ptr->m_free_ptr.cas(old_free_ptr, old_free_ptr->next.get_ptr()))
00092 return reinterpret_cast<void*>(old_free_ptr.get_ptr());
00093 }
00094 #endif
00095
00096 boost::unique_lock<boost::mutex> pool_lock(pool_ptr->m_mutex);
00097 return pool_ptr->m_pool.ordered_malloc();
00098 }
00099
00106 inline void free(void *ptr, std::size_t n)
00107 {
00108
00109 if (n > MaxSize) {
00110 ::free(ptr);
00111 return;
00112 }
00113 FixedSizeAlloc *pool_ptr = getPool(n);
00114 #if defined(PION_HAVE_LOCKFREE)
00115 while (true) {
00116
00117 FreeListPtr old_free_ptr(pool_ptr->m_free_ptr);
00118
00119
00120
00121 FreeListNode *node_ptr = reinterpret_cast<FreeListNode*>(ptr);
00122 node_ptr->next.set_ptr(old_free_ptr.get_ptr());
00123
00124
00125 if (pool_ptr->m_free_ptr.cas(old_free_ptr, node_ptr))
00126 break;
00127 }
00128 #else
00129 boost::unique_lock<boost::mutex> pool_lock(pool_ptr->m_mutex);
00130 return pool_ptr->m_pool.ordered_free(ptr);
00131 #endif
00132 }
00133
00141 inline bool release_memory(size_t pad = 10240000UL)
00142 {
00143 bool result = false;
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 return result;
00170 }
00171
00172
00173 protected:
00174
00175 #if defined(PION_HAVE_LOCKFREE)
00177 struct FreeListNode {
00178 boost::lockfree::tagged_ptr<struct FreeListNode> next;
00179 };
00180
00182 typedef boost::lockfree::tagged_ptr<struct FreeListNode> FreeListPtr;
00183 #else
00184 typedef void * FreeListPtr;
00185 #endif
00186
00191 BOOST_STATIC_ASSERT(MaxSize >= MinSize);
00192 BOOST_STATIC_ASSERT(MaxSize % MinSize == 0);
00193 #if defined(PION_HAVE_LOCKFREE)
00194 BOOST_STATIC_ASSERT(MinSize >= sizeof(FreeListNode));
00195 #endif
00196
00198 enum { NumberOfAllocs = ((MaxSize-1) / MinSize) + 1 };
00199
00204 struct FixedSizeAlloc
00205 {
00211 FixedSizeAlloc(std::size_t size)
00212 : m_size(size), m_pool(size), m_free_ptr(NULL)
00213 {}
00214
00216 boost::mutex m_mutex;
00217
00219 std::size_t m_size;
00220
00222 boost::pool<> m_pool;
00223
00225 FreeListPtr m_free_ptr;
00226 };
00227
00228
00236 inline FixedSizeAlloc* getPool(const std::size_t n)
00237 {
00238 PION_ASSERT(n > 0);
00239 PION_ASSERT(n <= MaxSize);
00240 return m_pools[ (n-1) / MinSize ].get();
00241 }
00242
00243
00244 private:
00245
00247 boost::array<boost::scoped_ptr<FixedSizeAlloc>, NumberOfAllocs> m_pools;
00248 };
00249
00250
00251 }
00252
00253 #endif