allocate_array_helper.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright (c) 2012 Glen Joseph Fernandes
  3. * glenfe at live dot com
  4. *
  5. * Distributed under the Boost Software License,
  6. * Version 1.0. (See accompanying file LICENSE_1_0.txt
  7. * or copy at http://boost.org/LICENSE_1_0.txt)
  8. */
  9. #ifndef BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
  10. #define BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
  11. #include <boost/type_traits/alignment_of.hpp>
  12. namespace boost {
  13. namespace detail {
  14. template<typename A, typename T, typename Y = char>
  15. class allocate_array_helper;
  16. template<typename A, typename T, typename Y>
  17. class allocate_array_helper<A, T[], Y> {
  18. template<typename A9, typename T9, typename Y9>
  19. friend class allocate_array_helper;
  20. typedef typename A::template rebind<Y> ::other A2;
  21. typedef typename A::template rebind<char>::other A3;
  22. public:
  23. typedef typename A2::value_type value_type;
  24. typedef typename A2::pointer pointer;
  25. typedef typename A2::const_pointer const_pointer;
  26. typedef typename A2::reference reference;
  27. typedef typename A2::const_reference const_reference;
  28. typedef typename A2::size_type size_type;
  29. typedef typename A2::difference_type difference_type;
  30. template<typename U>
  31. struct rebind {
  32. typedef allocate_array_helper<A, T[], U> other;
  33. };
  34. allocate_array_helper(const A& allocator_, std::size_t size_, T** data_)
  35. : allocator(allocator_),
  36. size(sizeof(T) * size_),
  37. data(data_) {
  38. }
  39. template<class U>
  40. allocate_array_helper(const allocate_array_helper<A, T[], U>& other)
  41. : allocator(other.allocator),
  42. size(other.size),
  43. data(other.data) {
  44. }
  45. pointer address(reference value) const {
  46. return allocator.address(value);
  47. }
  48. const_pointer address(const_reference value) const {
  49. return allocator.address(value);
  50. }
  51. size_type max_size() const {
  52. return allocator.max_size();
  53. }
  54. pointer allocate(size_type count, const void* value = 0) {
  55. std::size_t a1 = boost::alignment_of<T>::value;
  56. std::size_t n1 = count * sizeof(Y) + a1 - 1;
  57. char* p1 = A3(allocator).allocate(n1 + size, value);
  58. char* p2 = p1 + n1;
  59. while (std::size_t(p2) % a1 != 0) {
  60. p2--;
  61. }
  62. *data = reinterpret_cast<T*>(p2);
  63. return reinterpret_cast<Y*>(p1);
  64. }
  65. void deallocate(pointer memory, size_type count) {
  66. std::size_t a1 = boost::alignment_of<T>::value;
  67. std::size_t n1 = count * sizeof(Y) + a1 - 1;
  68. char* p1 = reinterpret_cast<char*>(memory);
  69. A3(allocator).deallocate(p1, n1 + size);
  70. }
  71. void construct(pointer memory, const Y& value) {
  72. allocator.construct(memory, value);
  73. }
  74. void destroy(pointer memory) {
  75. allocator.destroy(memory);
  76. }
  77. template<typename U>
  78. bool operator==(const allocate_array_helper<A, T[], U>& other) const {
  79. return allocator == other.allocator;
  80. }
  81. template<typename U>
  82. bool operator!=(const allocate_array_helper<A, T[], U>& other) const {
  83. return !(*this == other);
  84. }
  85. private:
  86. A2 allocator;
  87. std::size_t size;
  88. T** data;
  89. };
  90. template<typename A, typename T, std::size_t N, typename Y>
  91. class allocate_array_helper<A, T[N], Y> {
  92. template<typename A9, typename T9, typename Y9>
  93. friend class allocate_array_helper;
  94. typedef typename A::template rebind<Y> ::other A2;
  95. typedef typename A::template rebind<char>::other A3;
  96. public:
  97. typedef typename A2::value_type value_type;
  98. typedef typename A2::pointer pointer;
  99. typedef typename A2::const_pointer const_pointer;
  100. typedef typename A2::reference reference;
  101. typedef typename A2::const_reference const_reference;
  102. typedef typename A2::size_type size_type;
  103. typedef typename A2::difference_type difference_type;
  104. template<typename U>
  105. struct rebind {
  106. typedef allocate_array_helper<A, T[N], U> other;
  107. };
  108. allocate_array_helper(const A& allocator_, T** data_)
  109. : allocator(allocator_),
  110. data(data_) {
  111. }
  112. template<class U>
  113. allocate_array_helper(const allocate_array_helper<A, T[N], U>& other)
  114. : allocator(other.allocator),
  115. data(other.data) {
  116. }
  117. pointer address(reference value) const {
  118. return allocator.address(value);
  119. }
  120. const_pointer address(const_reference value) const {
  121. return allocator.address(value);
  122. }
  123. size_type max_size() const {
  124. return allocator.max_size();
  125. }
  126. pointer allocate(size_type count, const void* value = 0) {
  127. std::size_t a1 = boost::alignment_of<T>::value;
  128. std::size_t n1 = count * sizeof(Y) + a1 - 1;
  129. char* p1 = A3(allocator).allocate(n1 + N1, value);
  130. char* p2 = p1 + n1;
  131. while (std::size_t(p2) % a1 != 0) {
  132. p2--;
  133. }
  134. *data = reinterpret_cast<T*>(p2);
  135. return reinterpret_cast<Y*>(p1);
  136. }
  137. void deallocate(pointer memory, size_type count) {
  138. std::size_t a1 = boost::alignment_of<T>::value;
  139. std::size_t n1 = count * sizeof(Y) + a1 - 1;
  140. char* p1 = reinterpret_cast<char*>(memory);
  141. A3(allocator).deallocate(p1, n1 + N1);
  142. }
  143. void construct(pointer memory, const Y& value) {
  144. allocator.construct(memory, value);
  145. }
  146. void destroy(pointer memory) {
  147. allocator.destroy(memory);
  148. }
  149. template<typename U>
  150. bool operator==(const allocate_array_helper<A, T[N], U>& other) const {
  151. return allocator == other.allocator;
  152. }
  153. template<typename U>
  154. bool operator!=(const allocate_array_helper<A, T[N], U>& other) const {
  155. return !(*this == other);
  156. }
  157. private:
  158. enum {
  159. N1 = N * sizeof(T)
  160. };
  161. A2 allocator;
  162. T** data;
  163. };
  164. }
  165. }
  166. #endif