allocator_version_traits.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2012-2012. 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_ALLOCATOR_VERSION_TRAITS_HPP
  11. #define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
  12. #if defined(_MSC_VER)
  13. # pragma once
  14. #endif
  15. #include <boost/container/detail/config_begin.hpp>
  16. #include <boost/container/detail/workaround.hpp>
  17. #include <boost/container/allocator_traits.hpp> //allocator_traits
  18. #include <boost/container/throw_exception.hpp>
  19. #include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
  20. #include <boost/container/detail/version_type.hpp> //version_type
  21. #include <boost/container/detail/allocation_type.hpp> //allocation_type
  22. #include <boost/container/detail/mpl.hpp> //integral_constant
  23. #include <boost/intrusive/pointer_traits.hpp> //pointer_traits
  24. #include <utility> //pair
  25. #include <boost/detail/no_exceptions_support.hpp> //BOOST_TRY
  26. namespace boost {
  27. namespace container {
  28. namespace container_detail {
  29. template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
  30. struct allocator_version_traits
  31. {
  32. typedef ::boost::container::container_detail::integral_constant
  33. <unsigned, Version> alloc_version;
  34. typedef typename Allocator::multiallocation_chain multiallocation_chain;
  35. typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
  36. typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
  37. //Node allocation interface
  38. static pointer allocate_one(Allocator &a)
  39. { return a.allocate_one(); }
  40. static void deallocate_one(Allocator &a, const pointer &p)
  41. { a.deallocate_one(p); }
  42. static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
  43. { return a.allocate_individual(n, m); }
  44. static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
  45. { a.deallocate_individual(holder); }
  46. static std::pair<pointer, bool>
  47. allocation_command(Allocator &a, allocation_type command,
  48. size_type limit_size, size_type preferred_size,
  49. size_type &received_size, const pointer &reuse)
  50. {
  51. return a.allocation_command
  52. (command, limit_size, preferred_size, received_size, reuse);
  53. }
  54. };
  55. template<class Allocator>
  56. struct allocator_version_traits<Allocator, 1>
  57. {
  58. typedef ::boost::container::container_detail::integral_constant
  59. <unsigned, 1> alloc_version;
  60. typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
  61. typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
  62. typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
  63. typedef typename boost::intrusive::pointer_traits<pointer>::
  64. template rebind_pointer<void>::type void_ptr;
  65. typedef container_detail::basic_multiallocation_chain
  66. <void_ptr> multialloc_cached_counted;
  67. typedef boost::container::container_detail::
  68. transform_multiallocation_chain
  69. < multialloc_cached_counted, value_type> multiallocation_chain;
  70. //Node allocation interface
  71. static pointer allocate_one(Allocator &a)
  72. { return a.allocate(1); }
  73. static void deallocate_one(Allocator &a, const pointer &p)
  74. { a.deallocate(p, 1); }
  75. static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
  76. {
  77. size_type n = holder.size();
  78. typename multiallocation_chain::iterator it = holder.begin();
  79. while(n--){
  80. pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it);
  81. ++it;
  82. a.deallocate(p, 1);
  83. }
  84. }
  85. struct allocate_individual_rollback
  86. {
  87. allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
  88. : mr_a(a), mp_chain(&chain)
  89. {}
  90. ~allocate_individual_rollback()
  91. {
  92. if(mp_chain)
  93. allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
  94. }
  95. void release()
  96. {
  97. mp_chain = 0;
  98. }
  99. Allocator &mr_a;
  100. multiallocation_chain * mp_chain;
  101. };
  102. static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
  103. {
  104. allocate_individual_rollback rollback(a, m);
  105. while(n--){
  106. m.push_front(a.allocate(1));
  107. }
  108. rollback.release();
  109. }
  110. static std::pair<pointer, bool>
  111. allocation_command(Allocator &a, allocation_type command,
  112. size_type, size_type preferred_size,
  113. size_type &received_size, const pointer &)
  114. {
  115. std::pair<pointer, bool> ret(pointer(), false);
  116. if(!(command & allocate_new)){
  117. if(!(command & nothrow_allocation)){
  118. throw_logic_error("version 1 allocator without allocate_new flag");
  119. }
  120. }
  121. else{
  122. received_size = preferred_size;
  123. BOOST_TRY{
  124. ret.first = a.allocate(received_size);
  125. }
  126. BOOST_CATCH(...){
  127. if(!(command & nothrow_allocation)){
  128. BOOST_RETHROW
  129. }
  130. }
  131. BOOST_CATCH_END
  132. }
  133. return ret;
  134. }
  135. };
  136. } //namespace container_detail {
  137. } //namespace container {
  138. } //namespace boost {
  139. #include <boost/container/detail/config_end.hpp>
  140. #endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)