319 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			319 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2012-2014 Glen Joseph Fernandes 
							 | 
						||
| 
								 | 
							
								 * glenfe at live dot com
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Distributed under the Boost Software License, 
							 | 
						||
| 
								 | 
							
								 * Version 1.0. (See accompanying file LICENSE_1_0.txt 
							 | 
						||
| 
								 | 
							
								 * or copy at http://boost.org/LICENSE_1_0.txt)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
							 | 
						||
| 
								 | 
							
								#define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/align/align.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/smart_ptr/detail/array_traits.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/smart_ptr/detail/array_utility.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/alignment_of.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost {
							 | 
						||
| 
								 | 
							
								    namespace detail {
							 | 
						||
| 
								 | 
							
								        struct ms_init_tag   { };
							 | 
						||
| 
								 | 
							
								        struct ms_noinit_tag { };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class T>
							 | 
						||
| 
								 | 
							
								        struct ms_allocator_state;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class T>
							 | 
						||
| 
								 | 
							
								        struct ms_allocator_state<T[]> {
							 | 
						||
| 
								 | 
							
								            typedef typename array_base<T>::type type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            ms_allocator_state(std::size_t size_,
							 | 
						||
| 
								 | 
							
								                type** result_)
							 | 
						||
| 
								 | 
							
								                : size(size_ * array_total<T>::size),
							 | 
						||
| 
								 | 
							
								                  result(result_) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            std::size_t size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            union {
							 | 
						||
| 
								 | 
							
								                type** result;
							 | 
						||
| 
								 | 
							
								                type* object;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class T, std::size_t N>
							 | 
						||
| 
								 | 
							
								        struct ms_allocator_state<T[N]> {
							 | 
						||
| 
								 | 
							
								            typedef typename array_base<T>::type type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            ms_allocator_state(type** result_)
							 | 
						||
| 
								 | 
							
								                : result(result_) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            enum {
							 | 
						||
| 
								 | 
							
								                size = array_total<T[N]>::size
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            union {
							 | 
						||
| 
								 | 
							
								                type** result;
							 | 
						||
| 
								 | 
							
								                type* object;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class A, class T, class R>
							 | 
						||
| 
								 | 
							
								        class as_allocator
							 | 
						||
| 
								 | 
							
								            : public A {
							 | 
						||
| 
								 | 
							
								            template<class A_, class T_, class R_>
							 | 
						||
| 
								 | 
							
								            friend class as_allocator;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if !defined(BOOST_NO_CXX11_ALLOCATOR)
							 | 
						||
| 
								 | 
							
								            typedef std::allocator_traits<A> AT;
							 | 
						||
| 
								 | 
							
								            typedef typename AT::template rebind_alloc<char> CA;
							 | 
						||
| 
								 | 
							
								            typedef typename AT::template rebind_traits<char> CT;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								            typedef typename A::template rebind<char>::other CA;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public:
							 | 
						||
| 
								 | 
							
								            typedef A allocator_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if !defined(BOOST_NO_CXX11_ALLOCATOR)
							 | 
						||
| 
								 | 
							
								            typedef typename AT::value_type value_type;
							 | 
						||
| 
								 | 
							
								            typedef typename AT::pointer pointer;
							 | 
						||
| 
								 | 
							
								            typedef typename AT::const_pointer const_pointer;
							 | 
						||
| 
								 | 
							
								            typedef typename AT::void_pointer void_pointer;
							 | 
						||
| 
								 | 
							
								            typedef typename AT::const_void_pointer const_void_pointer;
							 | 
						||
| 
								 | 
							
								            typedef typename AT::size_type size_type;
							 | 
						||
| 
								 | 
							
								            typedef typename AT::difference_type difference_type;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								            typedef typename A::value_type value_type;
							 | 
						||
| 
								 | 
							
								            typedef typename A::pointer pointer;
							 | 
						||
| 
								 | 
							
								            typedef typename A::const_pointer const_pointer;
							 | 
						||
| 
								 | 
							
								            typedef typename A::size_type size_type;
							 | 
						||
| 
								 | 
							
								            typedef typename A::difference_type difference_type;
							 | 
						||
| 
								 | 
							
								            typedef typename A::reference reference;
							 | 
						||
| 
								 | 
							
								            typedef typename A::const_reference const_reference;
							 | 
						||
| 
								 | 
							
								            typedef void* void_pointer;
							 | 
						||
| 
								 | 
							
								            typedef const void* const_void_pointer;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            template<class U>
							 | 
						||
| 
								 | 
							
								            struct rebind {
							 | 
						||
| 
								 | 
							
								#if !defined(BOOST_NO_CXX11_ALLOCATOR)
							 | 
						||
| 
								 | 
							
								                typedef as_allocator<typename AT::
							 | 
						||
| 
								 | 
							
								                    template rebind_alloc<U>, T, R> other;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								                typedef as_allocator<typename A::
							 | 
						||
| 
								 | 
							
								                    template rebind<U>::other, T, R> other;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            typedef typename array_base<T>::type type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            as_allocator(const A& allocator_, type** result)
							 | 
						||
| 
								 | 
							
								                : A(allocator_),
							 | 
						||
| 
								 | 
							
								                  data(result) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            as_allocator(const A& allocator_, std::size_t size,
							 | 
						||
| 
								 | 
							
								                type** result)
							 | 
						||
| 
								 | 
							
								                : A(allocator_),
							 | 
						||
| 
								 | 
							
								                  data(size, result) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            template<class U>
							 | 
						||
| 
								 | 
							
								            as_allocator(const as_allocator<U, T, R>& other)
							 | 
						||
| 
								 | 
							
								                : A(other.allocator()),
							 | 
						||
| 
								 | 
							
								                  data(other.data) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            pointer allocate(size_type count, const_void_pointer = 0) {
							 | 
						||
| 
								 | 
							
								                enum {
							 | 
						||
| 
								 | 
							
								                    M = boost::alignment_of<type>::value
							 | 
						||
| 
								 | 
							
								                };
							 | 
						||
| 
								 | 
							
								                std::size_t n1 = count * sizeof(value_type);
							 | 
						||
| 
								 | 
							
								                std::size_t n2 = data.size * sizeof(type);
							 | 
						||
| 
								 | 
							
								                std::size_t n3 = n2 + M;
							 | 
						||
| 
								 | 
							
								                CA ca(allocator());
							 | 
						||
| 
								 | 
							
								                void* p1 = ca.allocate(n1 + n3);
							 | 
						||
| 
								 | 
							
								                void* p2 = static_cast<char*>(p1) + n1;
							 | 
						||
| 
								 | 
							
								                (void)boost::alignment::align(M, n2, p2, n3);
							 | 
						||
| 
								 | 
							
								                *data.result = static_cast<type*>(p2);
							 | 
						||
| 
								 | 
							
								                return static_cast<value_type*>(p1);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void deallocate(pointer memory, size_type count) {
							 | 
						||
| 
								 | 
							
								                enum {
							 | 
						||
| 
								 | 
							
								                    M = boost::alignment_of<type>::value
							 | 
						||
| 
								 | 
							
								                };
							 | 
						||
| 
								 | 
							
								                std::size_t n1 = count * sizeof(value_type);
							 | 
						||
| 
								 | 
							
								                std::size_t n2 = data.size * sizeof(type) + M;
							 | 
						||
| 
								 | 
							
								                char* p1 = reinterpret_cast<char*>(memory);
							 | 
						||
| 
								 | 
							
								                CA ca(allocator());
							 | 
						||
| 
								 | 
							
								                ca.deallocate(p1, n1 + n2);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            const A& allocator() const {
							 | 
						||
| 
								 | 
							
								                return static_cast<const A&>(*this);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            A& allocator() {
							 | 
						||
| 
								 | 
							
								                return static_cast<A&>(*this);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void set(type* memory) {
							 | 
						||
| 
								 | 
							
								                data.object = memory;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void operator()() {
							 | 
						||
| 
								 | 
							
								                if (data.object) {
							 | 
						||
| 
								 | 
							
								                    R tag;
							 | 
						||
| 
								 | 
							
								                    release(tag);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private:
							 | 
						||
| 
								 | 
							
								            void release(ms_init_tag) {
							 | 
						||
| 
								 | 
							
								#if !defined(BOOST_NO_CXX11_ALLOCATOR)
							 | 
						||
| 
								 | 
							
								                as_destroy(allocator(), data.object, data.size);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								                ms_destroy(data.object, data.size);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void release(ms_noinit_tag) {
							 | 
						||
| 
								 | 
							
								                ms_destroy(data.object, data.size);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            ms_allocator_state<T> data;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class A1, class A2, class T, class R>
							 | 
						||
| 
								 | 
							
								        bool operator==(const as_allocator<A1, T, R>& a1,
							 | 
						||
| 
								 | 
							
								            const as_allocator<A2, T, R>& a2) {
							 | 
						||
| 
								 | 
							
								            return a1.allocator() == a2.allocator();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class A1, class A2, class T, class R>
							 | 
						||
| 
								 | 
							
								        bool operator!=(const as_allocator<A1, T, R>& a1,
							 | 
						||
| 
								 | 
							
								            const as_allocator<A2, T, R>& a2) {
							 | 
						||
| 
								 | 
							
								            return a1.allocator() != a2.allocator();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class T, class Y = char>
							 | 
						||
| 
								 | 
							
								        class ms_allocator;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class T, class Y>
							 | 
						||
| 
								 | 
							
								        class ms_allocator {
							 | 
						||
| 
								 | 
							
								            template<class T_, class Y_>
							 | 
						||
| 
								 | 
							
								            friend class ms_allocator;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public:
							 | 
						||
| 
								 | 
							
								            typedef typename array_base<T>::type type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            typedef Y value_type;
							 | 
						||
| 
								 | 
							
								            typedef Y* pointer;
							 | 
						||
| 
								 | 
							
								            typedef const Y* const_pointer;
							 | 
						||
| 
								 | 
							
								            typedef std::size_t size_type;
							 | 
						||
| 
								 | 
							
								            typedef std::ptrdiff_t difference_type;
							 | 
						||
| 
								 | 
							
								            typedef Y& reference;
							 | 
						||
| 
								 | 
							
								            typedef const Y& const_reference;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            template<class U>
							 | 
						||
| 
								 | 
							
								            struct rebind {
							 | 
						||
| 
								 | 
							
								                typedef ms_allocator<T, U> other;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            ms_allocator(type** result)
							 | 
						||
| 
								 | 
							
								                : data(result) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            ms_allocator(std::size_t size, type** result)
							 | 
						||
| 
								 | 
							
								                : data(size, result) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            template<class U>
							 | 
						||
| 
								 | 
							
								            ms_allocator(const ms_allocator<T, U>& other)
							 | 
						||
| 
								 | 
							
								                : data(other.data) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            pointer allocate(size_type count, const void* = 0) {
							 | 
						||
| 
								 | 
							
								                enum {
							 | 
						||
| 
								 | 
							
								                    M = boost::alignment_of<type>::value
							 | 
						||
| 
								 | 
							
								                };
							 | 
						||
| 
								 | 
							
								                std::size_t n1 = count * sizeof(Y);
							 | 
						||
| 
								 | 
							
								                std::size_t n2 = data.size * sizeof(type);
							 | 
						||
| 
								 | 
							
								                std::size_t n3 = n2 + M;
							 | 
						||
| 
								 | 
							
								                void* p1 = ::operator new(n1 + n3);
							 | 
						||
| 
								 | 
							
								                void* p2 = static_cast<char*>(p1) + n1;
							 | 
						||
| 
								 | 
							
								                (void)boost::alignment::align(M, n2, p2, n3);
							 | 
						||
| 
								 | 
							
								                *data.result = static_cast<type*>(p2);
							 | 
						||
| 
								 | 
							
								                return static_cast<Y*>(p1);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void deallocate(pointer memory, size_type) {
							 | 
						||
| 
								 | 
							
								                void* p1 = memory;
							 | 
						||
| 
								 | 
							
								                ::operator delete(p1);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(BOOST_NO_CXX11_ALLOCATOR)
							 | 
						||
| 
								 | 
							
								            pointer address(reference value) const {
							 | 
						||
| 
								 | 
							
								                return &value;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            const_pointer address(const_reference value) const {
							 | 
						||
| 
								 | 
							
								                return &value;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            size_type max_size() const {
							 | 
						||
| 
								 | 
							
								                enum {
							 | 
						||
| 
								 | 
							
								                    N = static_cast<std::size_t>(-1) / sizeof(Y)
							 | 
						||
| 
								 | 
							
								                };
							 | 
						||
| 
								 | 
							
								                return N;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void construct(pointer memory, const_reference value) {
							 | 
						||
| 
								 | 
							
								                void* p1 = memory;
							 | 
						||
| 
								 | 
							
								                ::new(p1) Y(value);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void destroy(pointer memory) {
							 | 
						||
| 
								 | 
							
								                (void)memory;
							 | 
						||
| 
								 | 
							
								                memory->~Y();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void set(type* memory) {
							 | 
						||
| 
								 | 
							
								                data.object = memory;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            void operator()() {
							 | 
						||
| 
								 | 
							
								                if (data.object) {
							 | 
						||
| 
								 | 
							
								                    ms_destroy(data.object, data.size);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        private:
							 | 
						||
| 
								 | 
							
								            ms_allocator_state<T> data;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class T, class Y1, class Y2>
							 | 
						||
| 
								 | 
							
								        bool operator==(const ms_allocator<T, Y1>&,
							 | 
						||
| 
								 | 
							
								            const ms_allocator<T, Y2>&) {
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<class T, class Y1, class Y2>
							 | 
						||
| 
								 | 
							
								        bool operator!=(const ms_allocator<T, Y1>&,
							 | 
						||
| 
								 | 
							
								            const ms_allocator<T, Y2>&) {
							 | 
						||
| 
								 | 
							
								            return false;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        class ms_in_allocator_tag {
							 | 
						||
| 
								 | 
							
								        public:
							 | 
						||
| 
								 | 
							
								            void operator()(const void*) {
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |