File indexing completed on 2025-01-18 09:30:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_CONTAINER_ALLOCATOR_HPP
0012 #define BOOST_CONTAINER_ALLOCATOR_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/container/detail/config_begin.hpp>
0023 #include <boost/container/detail/workaround.hpp>
0024 #include <boost/container/container_fwd.hpp>
0025 #include <boost/container/detail/version_type.hpp>
0026 #include <boost/container/throw_exception.hpp>
0027 #include <boost/container/detail/dlmalloc.hpp>
0028 #include <boost/container/detail/multiallocation_chain.hpp>
0029 #include <boost/static_assert.hpp>
0030
0031 #include <boost/move/detail/force_ptr.hpp>
0032
0033 #include <cstddef>
0034 #include <cassert>
0035
0036
0037
0038 namespace boost {
0039 namespace container {
0040
0041 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0042
0043 template<unsigned Version, unsigned int AllocationDisableMask>
0044 class allocator<void, Version, AllocationDisableMask>
0045 {
0046 typedef allocator<void, Version, AllocationDisableMask> self_t;
0047 public:
0048 typedef void value_type;
0049 typedef void * pointer;
0050 typedef const void* const_pointer;
0051 typedef int & reference;
0052 typedef const int & const_reference;
0053 typedef std::size_t size_type;
0054 typedef std::ptrdiff_t difference_type;
0055 typedef boost::container::dtl::
0056 version_type<self_t, Version> version;
0057
0058 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0059 typedef boost::container::dtl::
0060 basic_multiallocation_chain<void*> multiallocation_chain;
0061 #endif
0062
0063
0064
0065 template<class T2>
0066 struct rebind
0067 {
0068 typedef allocator< T2
0069 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0070 , Version, AllocationDisableMask
0071 #endif
0072 > other;
0073 };
0074
0075
0076
0077 allocator()
0078 {}
0079
0080
0081
0082 allocator(const allocator &)
0083 {}
0084
0085
0086
0087 template<class T2>
0088 allocator(const allocator<T2, Version, AllocationDisableMask> &)
0089 {}
0090 };
0091
0092 #endif
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 template< class T
0104 , unsigned Version BOOST_CONTAINER_DOCONLY(=2)
0105 , unsigned int AllocationDisableMask BOOST_CONTAINER_DOCONLY(=0)>
0106 class allocator
0107 {
0108 typedef unsigned int allocation_type;
0109 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0110 private:
0111
0112
0113 typedef allocator<T, Version, AllocationDisableMask> self_t;
0114
0115
0116 template<class T2, unsigned int Version2, unsigned int AllocationDisableMask2>
0117 allocator& operator=(const allocator<T2, Version2, AllocationDisableMask2>&);
0118
0119 static const unsigned int ForbiddenMask =
0120 BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BWD | BOOST_CONTAINER_EXPAND_FWD ;
0121
0122
0123 BOOST_STATIC_ASSERT(( (AllocationDisableMask & ForbiddenMask) != ForbiddenMask ));
0124
0125
0126 BOOST_STATIC_ASSERT(( Version != 1 || (AllocationDisableMask == 0) ));
0127
0128 #endif
0129
0130 public:
0131 typedef T value_type;
0132 typedef T * pointer;
0133 typedef const T * const_pointer;
0134 typedef T & reference;
0135 typedef const T & const_reference;
0136 typedef std::size_t size_type;
0137 typedef std::ptrdiff_t difference_type;
0138
0139 typedef boost::container::dtl::
0140 version_type<self_t, Version> version;
0141
0142 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0143 typedef boost::container::dtl::
0144 basic_multiallocation_chain<void*> void_multiallocation_chain;
0145
0146 typedef boost::container::dtl::
0147 transform_multiallocation_chain
0148 <void_multiallocation_chain, T> multiallocation_chain;
0149 #endif
0150
0151
0152
0153 template<class T2>
0154 struct rebind
0155 {
0156 typedef allocator<T2, Version, AllocationDisableMask> other;
0157 };
0158
0159
0160
0161 allocator() BOOST_NOEXCEPT_OR_NOTHROW
0162 {}
0163
0164
0165
0166 allocator(const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
0167 {}
0168
0169
0170
0171 template<class T2>
0172 allocator(const allocator<T2
0173 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0174 , Version, AllocationDisableMask
0175 #endif
0176 > &) BOOST_NOEXCEPT_OR_NOTHROW
0177 {}
0178
0179
0180
0181
0182
0183 BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate(size_type count, const void * hint= 0)
0184 {
0185 (void)hint;
0186 if(count > size_type(-1)/(2u*sizeof(T)))
0187 boost::container::throw_bad_alloc();
0188 void *ret = dlmalloc_malloc(count*sizeof(T));
0189 if(!ret)
0190 boost::container::throw_bad_alloc();
0191 return static_cast<pointer>(ret);
0192 }
0193
0194
0195
0196 BOOST_CONTAINER_FORCEINLINE void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW
0197 { dlmalloc_free(ptr); }
0198
0199
0200
0201 BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
0202 { return size_type(-1)/(2u*sizeof(T)); }
0203
0204
0205
0206 BOOST_CONTAINER_FORCEINLINE friend void swap(self_t &, self_t &) BOOST_NOEXCEPT_OR_NOTHROW
0207 {}
0208
0209
0210
0211 BOOST_CONTAINER_ATTRIBUTE_NODISCARD
0212 friend bool operator==(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
0213 { return true; }
0214
0215
0216
0217 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0218 friend bool operator!=(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
0219 { return false; }
0220
0221
0222
0223
0224
0225 BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocation_command(allocation_type command,
0226 size_type limit_size,
0227 size_type &prefer_in_recvd_out_size,
0228 pointer &reuse)
0229 {
0230 BOOST_STATIC_ASSERT(( Version > 1 ));
0231 const allocation_type mask(AllocationDisableMask);
0232 command &= ~mask;
0233 pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
0234 if(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
0235 boost::container::throw_bad_alloc();
0236 return ret;
0237 }
0238
0239
0240
0241
0242
0243
0244 BOOST_CONTAINER_ATTRIBUTE_NODISCARD size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
0245 {
0246 BOOST_STATIC_ASSERT(( Version > 1 ));
0247 return dlmalloc_size(p);
0248 }
0249
0250
0251
0252
0253
0254 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE pointer allocate_one()
0255 {
0256 BOOST_STATIC_ASSERT(( Version > 1 ));
0257 return this->allocate(1);
0258 }
0259
0260
0261
0262
0263 BOOST_CONTAINER_FORCEINLINE void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
0264 {
0265 BOOST_STATIC_ASSERT(( Version > 1 ));
0266 this->allocate_many(1, num_elements, chain);
0267 }
0268
0269
0270
0271
0272
0273 void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
0274 {
0275 BOOST_STATIC_ASSERT(( Version > 1 ));
0276 return this->deallocate(p, 1);
0277 }
0278
0279
0280
0281 BOOST_CONTAINER_FORCEINLINE
0282 void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
0283 {
0284 BOOST_STATIC_ASSERT(( Version > 1 ));
0285 return this->deallocate_many(chain);
0286 }
0287
0288
0289
0290
0291 void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
0292 {
0293 BOOST_STATIC_ASSERT(( Version > 1 ));
0294 dlmalloc_memchain ch;
0295 BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
0296 if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
0297 boost::container::throw_bad_alloc();
0298 }
0299 chain.incorporate_after(chain.before_begin()
0300 ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
0301 ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
0302 ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
0303
0304
0305
0306
0307
0308 }
0309
0310
0311
0312
0313 void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
0314 {
0315 BOOST_STATIC_ASSERT(( Version > 1 ));
0316 dlmalloc_memchain ch;
0317 BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
0318 if(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
0319 boost::container::throw_bad_alloc();
0320 }
0321 chain.incorporate_after(chain.before_begin()
0322 ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
0323 ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
0324 ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
0325
0326
0327
0328
0329
0330 }
0331
0332
0333
0334
0335 void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
0336 {
0337 BOOST_STATIC_ASSERT(( Version > 1 ));
0338 dlmalloc_memchain ch;
0339 void *beg(&*chain.begin()), *last(&*chain.last());
0340 size_t size(chain.size());
0341 BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
0342 dlmalloc_multidealloc(&ch);
0343
0344 }
0345
0346 private:
0347
0348 pointer priv_allocation_command
0349 (allocation_type command, std::size_t limit_size
0350 ,size_type &prefer_in_recvd_out_size
0351 ,pointer &reuse_ptr)
0352 {
0353 std::size_t const preferred_size = prefer_in_recvd_out_size;
0354 dlmalloc_command_ret_t ret = {0 , 0};
0355 if((limit_size > this->max_size()) || (preferred_size > this->max_size())){
0356 return pointer();
0357 }
0358 std::size_t l_size = limit_size*sizeof(T);
0359 std::size_t p_size = preferred_size*sizeof(T);
0360 std::size_t r_size;
0361 {
0362 void* reuse_ptr_void = reuse_ptr;
0363 ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
0364 reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
0365 }
0366 prefer_in_recvd_out_size = r_size/sizeof(T);
0367 return (pointer)ret.first;
0368 }
0369 };
0370
0371 }
0372 }
0373
0374 #include <boost/container/detail/config_end.hpp>
0375
0376 #endif
0377