guards_dended.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Benedek Thaler 2015-2016
  4. // (C) Copyright Ion Gaztanaga 2019-2020. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://erenon.hu/container for documentation.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. #ifndef BOOST_CONTAINER_DETAIL_GUARDS_HPP
  12. #define BOOST_CONTAINER_DETAIL_GUARDS_HPP
  13. #include <boost/container/detail/config_begin.hpp>
  14. #include <boost/container/detail/workaround.hpp>
  15. #include <boost/move/core.hpp> // BOOST_MOVABLE_BUT_NOT_COPYABLE
  16. // move/detail
  17. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  18. #include <boost/move/detail/fwd_macros.hpp>
  19. #endif
  20. #include <boost/container/allocator_traits.hpp>
  21. namespace boost {
  22. namespace container {
  23. namespace detail {
  24. class null_construction_guard
  25. {
  26. public:
  27. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  28. template <typename... Args>
  29. null_construction_guard(Args&&...) {}
  30. #else
  31. #define NULL_CONSTRUCTION_GUARD_CODE(N) \
  32. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  33. BOOST_CONTAINER_FORCEINLINE null_construction_guard(BOOST_MOVE_UREFANON##N)\
  34. {}\
  35. //
  36. BOOST_MOVE_ITERATE_0TO9(NULL_CONSTRUCTION_GUARD_CODE)
  37. #undef NULL_CONSTRUCTION_GUARD_CODE
  38. #endif
  39. void release() {}
  40. void extend() {}
  41. };
  42. template <typename Allocator>
  43. class construction_guard
  44. {
  45. typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
  46. typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
  47. BOOST_MOVABLE_BUT_NOT_COPYABLE(construction_guard)
  48. public:
  49. construction_guard()
  50. : _alloc_ptr()
  51. , _elem_count()
  52. , _allocator()
  53. {}
  54. construction_guard(pointer alloc_ptr, Allocator& allocator)
  55. :_alloc_ptr(alloc_ptr)
  56. , _elem_count(0)
  57. , _allocator(&allocator)
  58. {}
  59. construction_guard(BOOST_RV_REF(construction_guard) rhs)
  60. :_alloc_ptr(rhs._alloc_ptr)
  61. , _elem_count(rhs._elem_count)
  62. , _allocator(rhs._allocator)
  63. {
  64. rhs._elem_count = 0;
  65. }
  66. ~construction_guard()
  67. {
  68. while (_elem_count) {
  69. --_elem_count;
  70. boost::container::allocator_traits<Allocator>::destroy(*_allocator, _alloc_ptr++);
  71. }
  72. }
  73. void release()
  74. {
  75. _elem_count = 0;
  76. }
  77. void extend()
  78. {
  79. ++_elem_count;
  80. }
  81. private:
  82. pointer _alloc_ptr;
  83. size_type _elem_count;
  84. Allocator* _allocator;
  85. };
  86. /**
  87. * Has two ranges
  88. *
  89. * On success, destroys the first range (src),
  90. * on failure, destroys the second range (dst).
  91. *
  92. * Can be used when copying/moving a range
  93. */
  94. template <class Allocator>
  95. class nand_construction_guard
  96. {
  97. typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
  98. typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
  99. construction_guard<Allocator> _src;
  100. construction_guard<Allocator> _dst;
  101. bool _dst_released;
  102. public:
  103. nand_construction_guard()
  104. : _src()
  105. , _dst()
  106. , _dst_released(false)
  107. {}
  108. nand_construction_guard( pointer src, Allocator& src_alloc
  109. , pointer dst, Allocator& dst_alloc)
  110. :_src(src, src_alloc),
  111. _dst(dst, dst_alloc),
  112. _dst_released(false)
  113. {}
  114. void extend()
  115. {
  116. _src.extend();
  117. _dst.extend();
  118. }
  119. void release() // on success
  120. {
  121. _dst.release();
  122. _dst_released = true;
  123. }
  124. ~nand_construction_guard()
  125. {
  126. if (! _dst_released) { _src.release(); }
  127. }
  128. };
  129. template <typename Allocator>
  130. class allocation_guard
  131. {
  132. typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
  133. typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
  134. BOOST_MOVABLE_BUT_NOT_COPYABLE(allocation_guard)
  135. public:
  136. allocation_guard(pointer alloc_ptr, size_type alloc_size, Allocator& allocator)
  137. :_alloc_ptr(alloc_ptr),
  138. _alloc_size(alloc_size),
  139. _allocator(allocator)
  140. {}
  141. ~allocation_guard()
  142. {
  143. if (_alloc_ptr)
  144. {
  145. boost::container::allocator_traits<Allocator>::deallocate(_allocator, _alloc_ptr, _alloc_size);
  146. }
  147. }
  148. void release()
  149. {
  150. _alloc_ptr = 0;
  151. }
  152. private:
  153. pointer _alloc_ptr;
  154. size_type _alloc_size;
  155. Allocator& _allocator;
  156. };
  157. }}} // namespace boost::container::detail
  158. #include <boost/container/detail/config_end.hpp>
  159. #endif // BOOST_CONTAINER_DETAIL_GUARDS_HPP