expand_bwd_test_allocator.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
  11. #define BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
  12. #ifndef BOOST_CONFIG_HPP
  13. # include <boost/config.hpp>
  14. #endif
  15. #if defined(BOOST_HAS_PRAGMA_ONCE)
  16. # pragma once
  17. #endif
  18. #include <boost/container/detail/config_begin.hpp>
  19. #include <boost/container/detail/workaround.hpp>
  20. #include <boost/container/container_fwd.hpp>
  21. #include <boost/container/throw_exception.hpp>
  22. #include <boost/container/detail/addressof.hpp>
  23. #include <boost/container/detail/allocation_type.hpp>
  24. #include <boost/container/detail/version_type.hpp>
  25. #include <boost/move/adl_move_swap.hpp>
  26. #include <boost/assert.hpp>
  27. #include <memory>
  28. #include <algorithm>
  29. #include <cstddef>
  30. #include <cassert>
  31. namespace boost {
  32. namespace container {
  33. namespace test {
  34. //This allocator just allows two allocations. The first one will return
  35. //mp_buffer + m_offset configured in the constructor. The second one
  36. //will return mp_buffer.
  37. template<class T>
  38. class expand_bwd_test_allocator
  39. {
  40. private:
  41. typedef expand_bwd_test_allocator<T> self_t;
  42. typedef void * aux_pointer_t;
  43. typedef const void * cvoid_ptr;
  44. template<class T2>
  45. expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator<T2>&);
  46. expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&);
  47. public:
  48. typedef T value_type;
  49. typedef T * pointer;
  50. typedef const T * const_pointer;
  51. typedef typename dtl::add_reference
  52. <value_type>::type reference;
  53. typedef typename dtl::add_reference
  54. <const value_type>::type const_reference;
  55. typedef std::size_t size_type;
  56. typedef std::ptrdiff_t difference_type;
  57. typedef boost::container::dtl::version_type<expand_bwd_test_allocator, 2> version;
  58. //Dummy multiallocation chain
  59. struct multiallocation_chain{};
  60. template<class T2>
  61. struct rebind
  62. { typedef expand_bwd_test_allocator<T2> other; };
  63. //!Constructor from the segment manager. Never throws
  64. expand_bwd_test_allocator(T *buffer, size_type sz, difference_type offset)
  65. : mp_buffer(buffer), m_size(sz)
  66. , m_offset(offset), m_allocations(0){ }
  67. //!Constructor from other expand_bwd_test_allocator. Never throws
  68. expand_bwd_test_allocator(const expand_bwd_test_allocator &other)
  69. : mp_buffer(other.mp_buffer), m_size(other.m_size)
  70. , m_offset(other.m_offset), m_allocations(0){ }
  71. //!Constructor from related expand_bwd_test_allocator. Never throws
  72. template<class T2>
  73. expand_bwd_test_allocator(const expand_bwd_test_allocator<T2> &other)
  74. : mp_buffer(other.mp_buffer), m_size(other.m_size)
  75. , m_offset(other.m_offset), m_allocations(0){ }
  76. pointer address(reference value)
  77. { return pointer(dtl::addressof(value)); }
  78. const_pointer address(const_reference value) const
  79. { return const_pointer(dtl::addressof(value)); }
  80. pointer allocate(size_type , cvoid_ptr hint = 0)
  81. { (void)hint; return 0; }
  82. void deallocate(const pointer &, size_type)
  83. {}
  84. template<class Convertible>
  85. void construct(pointer ptr, const Convertible &value)
  86. { new((void*)ptr) value_type(value); }
  87. void destroy(pointer ptr)
  88. { (*ptr).~value_type(); }
  89. size_type max_size() const
  90. { return m_size; }
  91. friend void swap(self_t &alloc1, self_t &alloc2)
  92. {
  93. boost::adl_move_swap(alloc1.mp_buffer, alloc2.mp_buffer);
  94. boost::adl_move_swap(alloc1.m_size, alloc2.m_size);
  95. boost::adl_move_swap(alloc1.m_offset, alloc2.m_offset);
  96. }
  97. //Experimental version 2 expand_bwd_test_allocator functions
  98. pointer allocation_command(boost::container::allocation_type command,
  99. size_type limit_size,size_type &prefer_in_recvd_out_size,pointer &reuse)
  100. {
  101. (void)reuse; (void)command;
  102. //This allocator only expands backwards!
  103. assert(m_allocations == 0 || (command & boost::container::expand_bwd));
  104. prefer_in_recvd_out_size = limit_size;
  105. if(m_allocations == 0){
  106. if((m_offset + limit_size) > m_size){
  107. assert(0);
  108. }
  109. ++m_allocations;
  110. reuse = 0;
  111. return (mp_buffer + m_offset);
  112. }
  113. else if(m_allocations == 1){
  114. if(limit_size > m_size){
  115. assert(0);
  116. }
  117. ++m_allocations;
  118. return mp_buffer;
  119. }
  120. else{
  121. throw_bad_alloc();
  122. return mp_buffer;
  123. }
  124. }
  125. //!Returns maximum the number of objects the previously allocated memory
  126. //!pointed by p can hold.
  127. size_type size(const pointer &p) const
  128. { (void)p; return m_size; }
  129. //!Allocates just one object. Memory allocated with this function
  130. //!must be deallocated only with deallocate_one().
  131. //!Throws boost::container::bad_alloc if there is no enough memory
  132. pointer allocate_one()
  133. { return this->allocate(1); }
  134. //!Deallocates memory previously allocated with allocate_one().
  135. //!You should never use deallocate_one to deallocate memory allocated
  136. //!with other functions different from allocate_one(). Never throws
  137. void deallocate_one(const pointer &p)
  138. { return this->deallocate(p, 1); }
  139. pointer mp_buffer;
  140. size_type m_size;
  141. difference_type m_offset;
  142. char m_allocations;
  143. };
  144. //!Equality test for same type of expand_bwd_test_allocator
  145. template<class T> inline
  146. bool operator==(const expand_bwd_test_allocator<T> &,
  147. const expand_bwd_test_allocator<T> &)
  148. { return false; }
  149. //!Inequality test for same type of expand_bwd_test_allocator
  150. template<class T> inline
  151. bool operator!=(const expand_bwd_test_allocator<T> &,
  152. const expand_bwd_test_allocator<T> &)
  153. { return true; }
  154. } //namespace test {
  155. } //namespace container {
  156. } //namespace boost {
  157. #include <boost/container/detail/config_end.hpp>
  158. #endif //BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP