allocator_version_traits.hpp 5.5 KB

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