| 1 | #ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | 
|---|
| 2 | #define BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | 
|---|
| 3 |  | 
|---|
| 4 | // MS compatible compilers support #pragma once | 
|---|
| 5 |  | 
|---|
| 6 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) | 
|---|
| 7 | # pragma once | 
|---|
| 8 | #endif | 
|---|
| 9 |  | 
|---|
| 10 | // | 
|---|
| 11 | //  detail/quick_allocator.hpp | 
|---|
| 12 | // | 
|---|
| 13 | //  Copyright (c) 2003 David Abrahams | 
|---|
| 14 | //  Copyright (c) 2003 Peter Dimov | 
|---|
| 15 | // | 
|---|
| 16 | // Distributed under the Boost Software License, Version 1.0. (See | 
|---|
| 17 | // accompanying file LICENSE_1_0.txt or copy at | 
|---|
| 18 | // http://www.boost.org/LICENSE_1_0.txt) | 
|---|
| 19 | // | 
|---|
| 20 |  | 
|---|
| 21 | #include <boost/config.hpp> | 
|---|
| 22 |  | 
|---|
| 23 | #include <boost/detail/lightweight_mutex.hpp> | 
|---|
| 24 | #include <boost/type_traits/type_with_alignment.hpp> | 
|---|
| 25 | #include <boost/type_traits/alignment_of.hpp> | 
|---|
| 26 |  | 
|---|
| 27 | #include <new>              // ::operator new, ::operator delete | 
|---|
| 28 | #include <cstddef>          // std::size_t | 
|---|
| 29 |  | 
|---|
| 30 | namespace boost | 
|---|
| 31 | { | 
|---|
| 32 |  | 
|---|
| 33 | namespace detail | 
|---|
| 34 | { | 
|---|
| 35 |  | 
|---|
| 36 | template<unsigned size, unsigned align_> union freeblock | 
|---|
| 37 | { | 
|---|
| 38 |     typedef typename boost::type_with_alignment<align_>::type aligner_type; | 
|---|
| 39 |     aligner_type aligner; | 
|---|
| 40 |     char bytes[size]; | 
|---|
| 41 |     freeblock * next; | 
|---|
| 42 | }; | 
|---|
| 43 |  | 
|---|
| 44 | template<unsigned size, unsigned align_> struct allocator_impl | 
|---|
| 45 | { | 
|---|
| 46 |     typedef freeblock<size, align_> block; | 
|---|
| 47 |  | 
|---|
| 48 |     // It may seem odd to use such small pages. | 
|---|
| 49 |     // | 
|---|
| 50 |     // However, on a typical Windows implementation that uses | 
|---|
| 51 |     // the OS allocator, "normal size" pages interact with the | 
|---|
| 52 |     // "ordinary" operator new, slowing it down dramatically. | 
|---|
| 53 |     // | 
|---|
| 54 |     // 512 byte pages are handled by the small object allocator, | 
|---|
| 55 |     // and don't interfere with ::new. | 
|---|
| 56 |     // | 
|---|
| 57 |     // The other alternative is to use much bigger pages (1M.) | 
|---|
| 58 |     // | 
|---|
| 59 |     // It is surprisingly easy to hit pathological behavior by | 
|---|
| 60 |     // varying the page size. g++ 2.96 on Red Hat Linux 7.2, | 
|---|
| 61 |     // for example, passionately dislikes 496. 512 seems OK. | 
|---|
| 62 |  | 
|---|
| 63 | #if defined(BOOST_QA_PAGE_SIZE) | 
|---|
| 64 |  | 
|---|
| 65 |     enum { items_per_page = BOOST_QA_PAGE_SIZE / size }; | 
|---|
| 66 |  | 
|---|
| 67 | #else | 
|---|
| 68 |  | 
|---|
| 69 |     enum { items_per_page = 512 / size }; // 1048560 / size | 
|---|
| 70 |  | 
|---|
| 71 | #endif | 
|---|
| 72 |  | 
|---|
| 73 | #ifdef BOOST_HAS_THREADS | 
|---|
| 74 |  | 
|---|
| 75 |     static lightweight_mutex & mutex() | 
|---|
| 76 |     { | 
|---|
| 77 |         static lightweight_mutex m; | 
|---|
| 78 |         return m; | 
|---|
| 79 |     } | 
|---|
| 80 |  | 
|---|
| 81 |     static lightweight_mutex * mutex_init; | 
|---|
| 82 |  | 
|---|
| 83 | #endif | 
|---|
| 84 |  | 
|---|
| 85 |     static block * free; | 
|---|
| 86 |     static block * page; | 
|---|
| 87 |     static unsigned last; | 
|---|
| 88 |  | 
|---|
| 89 |     static inline void * alloc() | 
|---|
| 90 |     { | 
|---|
| 91 | #ifdef BOOST_HAS_THREADS | 
|---|
| 92 |         lightweight_mutex::scoped_lock lock( mutex() ); | 
|---|
| 93 | #endif | 
|---|
| 94 |         if(block * x = free) | 
|---|
| 95 |         { | 
|---|
| 96 |             free = x->next; | 
|---|
| 97 |             return x; | 
|---|
| 98 |         } | 
|---|
| 99 |         else | 
|---|
| 100 |         { | 
|---|
| 101 |             if(last == items_per_page) | 
|---|
| 102 |             { | 
|---|
| 103 |                 // "Listen to me carefully: there is no memory leak" | 
|---|
| 104 |                 // -- Scott Meyers, Eff C++ 2nd Ed Item 10 | 
|---|
| 105 |                 page = ::new block[items_per_page]; | 
|---|
| 106 |                 last = 0; | 
|---|
| 107 |             } | 
|---|
| 108 |  | 
|---|
| 109 |             return &page[last++]; | 
|---|
| 110 |         } | 
|---|
| 111 |     } | 
|---|
| 112 |  | 
|---|
| 113 |     static inline void * alloc(std::size_t n) | 
|---|
| 114 |     { | 
|---|
| 115 |         if(n != size) // class-specific new called for a derived object | 
|---|
| 116 |         { | 
|---|
| 117 |             return ::operator new(n); | 
|---|
| 118 |         } | 
|---|
| 119 |         else | 
|---|
| 120 |         { | 
|---|
| 121 | #ifdef BOOST_HAS_THREADS | 
|---|
| 122 |             lightweight_mutex::scoped_lock lock( mutex() ); | 
|---|
| 123 | #endif | 
|---|
| 124 |             if(block * x = free) | 
|---|
| 125 |             { | 
|---|
| 126 |                 free = x->next; | 
|---|
| 127 |                 return x; | 
|---|
| 128 |             } | 
|---|
| 129 |             else | 
|---|
| 130 |             { | 
|---|
| 131 |                 if(last == items_per_page) | 
|---|
| 132 |                 { | 
|---|
| 133 |                     page = ::new block[items_per_page]; | 
|---|
| 134 |                     last = 0; | 
|---|
| 135 |                 } | 
|---|
| 136 |  | 
|---|
| 137 |                 return &page[last++]; | 
|---|
| 138 |             } | 
|---|
| 139 |         } | 
|---|
| 140 |     } | 
|---|
| 141 |  | 
|---|
| 142 |     static inline void dealloc(void * pv) | 
|---|
| 143 |     { | 
|---|
| 144 |         if(pv != 0) // 18.4.1.1/13 | 
|---|
| 145 |         { | 
|---|
| 146 | #ifdef BOOST_HAS_THREADS | 
|---|
| 147 |             lightweight_mutex::scoped_lock lock( mutex() ); | 
|---|
| 148 | #endif | 
|---|
| 149 |             block * pb = static_cast<block *>(pv); | 
|---|
| 150 |             pb->next = free; | 
|---|
| 151 |             free = pb; | 
|---|
| 152 |         } | 
|---|
| 153 |     } | 
|---|
| 154 |  | 
|---|
| 155 |     static inline void dealloc(void * pv, std::size_t n) | 
|---|
| 156 |     { | 
|---|
| 157 |         if(n != size) // class-specific delete called for a derived object | 
|---|
| 158 |         { | 
|---|
| 159 |             ::operator delete(pv); | 
|---|
| 160 |         } | 
|---|
| 161 |         else if(pv != 0) // 18.4.1.1/13 | 
|---|
| 162 |         { | 
|---|
| 163 | #ifdef BOOST_HAS_THREADS | 
|---|
| 164 |             lightweight_mutex::scoped_lock lock( mutex() ); | 
|---|
| 165 | #endif | 
|---|
| 166 |             block * pb = static_cast<block *>(pv); | 
|---|
| 167 |             pb->next = free; | 
|---|
| 168 |             free = pb; | 
|---|
| 169 |         } | 
|---|
| 170 |     } | 
|---|
| 171 | }; | 
|---|
| 172 |  | 
|---|
| 173 | #ifdef BOOST_HAS_THREADS | 
|---|
| 174 |  | 
|---|
| 175 | template<unsigned size, unsigned align_> | 
|---|
| 176 |   lightweight_mutex * allocator_impl<size, align_>::mutex_init = &allocator_impl<size, align_>::mutex(); | 
|---|
| 177 |  | 
|---|
| 178 | #endif | 
|---|
| 179 |  | 
|---|
| 180 | template<unsigned size, unsigned align_> | 
|---|
| 181 |   freeblock<size, align_> * allocator_impl<size, align_>::free = 0; | 
|---|
| 182 |  | 
|---|
| 183 | template<unsigned size, unsigned align_> | 
|---|
| 184 |   freeblock<size, align_> * allocator_impl<size, align_>::page = 0; | 
|---|
| 185 |  | 
|---|
| 186 | template<unsigned size, unsigned align_> | 
|---|
| 187 |   unsigned allocator_impl<size, align_>::last = allocator_impl<size, align_>::items_per_page; | 
|---|
| 188 |  | 
|---|
| 189 | template<class T> | 
|---|
| 190 | struct quick_allocator: public allocator_impl< sizeof(T), boost::alignment_of<T>::value > | 
|---|
| 191 | { | 
|---|
| 192 | }; | 
|---|
| 193 |  | 
|---|
| 194 | } // namespace detail | 
|---|
| 195 |  | 
|---|
| 196 | } // namespace boost | 
|---|
| 197 |  | 
|---|
| 198 | #endif  // #ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | 
|---|