block_list.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2015-2015. 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_DETAIL_BLOCK_LIST_HEADER
  11. #define BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
  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/pmr/memory_resource.hpp>
  22. #include <boost/container/throw_exception.hpp>
  23. #include <boost/intrusive/circular_list_algorithms.hpp>
  24. #include <boost/move/detail/type_traits.hpp>
  25. #include <boost/assert.hpp>
  26. #include <cstddef>
  27. namespace boost {
  28. namespace container {
  29. namespace pmr {
  30. struct list_node
  31. {
  32. list_node *next;
  33. list_node *previous;
  34. };
  35. struct list_node_traits
  36. {
  37. typedef list_node node;
  38. typedef list_node* node_ptr;
  39. typedef const list_node* const_node_ptr;
  40. static node_ptr get_next(const_node_ptr n)
  41. { return n->next; }
  42. static node_ptr get_previous(const_node_ptr n)
  43. { return n->previous; }
  44. static void set_next(const node_ptr & n, const node_ptr & next)
  45. { n->next = next; }
  46. static void set_previous(const node_ptr & n, const node_ptr & previous)
  47. { n->previous = previous; }
  48. };
  49. struct block_list_header
  50. : public list_node
  51. {
  52. std::size_t size;
  53. };
  54. typedef bi::circular_list_algorithms<list_node_traits> list_algo;
  55. template<class DerivedFromBlockListHeader = block_list_header>
  56. class block_list_base
  57. {
  58. list_node m_list;
  59. static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
  60. public:
  61. static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockListHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1);
  62. explicit block_list_base()
  63. { list_algo::init_header(&m_list); }
  64. #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  65. block_list_base(const block_list_base&) = delete;
  66. block_list_base operator=(const block_list_base&) = delete;
  67. #else
  68. private:
  69. block_list_base (const block_list_base&);
  70. block_list_base operator=(const block_list_base&);
  71. public:
  72. #endif
  73. ~block_list_base()
  74. {}
  75. void *allocate(std::size_t size, memory_resource &mr)
  76. {
  77. if((size_t(-1) - header_size) < size)
  78. throw_bad_alloc();
  79. void *p = mr.allocate(size+header_size);
  80. block_list_header &mb = *::new((void*)p) DerivedFromBlockListHeader;
  81. mb.size = size+header_size;
  82. list_algo::link_after(&m_list, &mb);
  83. return (char *)p + header_size;
  84. }
  85. void deallocate(void *p, memory_resource &mr) BOOST_NOEXCEPT
  86. {
  87. DerivedFromBlockListHeader *pheader = static_cast<DerivedFromBlockListHeader*>
  88. (static_cast<void*>((char*)p - header_size));
  89. list_algo::unlink(pheader);
  90. const std::size_t size = pheader->size;
  91. static_cast<DerivedFromBlockListHeader*>(pheader)->~DerivedFromBlockListHeader();
  92. mr.deallocate(pheader, size, memory_resource::max_align);
  93. }
  94. void release(memory_resource &mr) BOOST_NOEXCEPT
  95. {
  96. list_node *n = list_algo::node_traits::get_next(&m_list);
  97. while(n != &m_list){
  98. DerivedFromBlockListHeader &d = static_cast<DerivedFromBlockListHeader&>(*n);
  99. n = list_algo::node_traits::get_next(n);
  100. std::size_t size = d.size;
  101. d.~DerivedFromBlockListHeader();
  102. mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align);
  103. }
  104. list_algo::init_header(&m_list);
  105. }
  106. };
  107. } //namespace pmr {
  108. } //namespace container {
  109. } //namespace boost {
  110. #include <boost/container/detail/config_end.hpp>
  111. #endif //BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER