handler_ptr.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_IMPL_HANDLER_PTR_HPP
  10. #define BOOST_BEAST_IMPL_HANDLER_PTR_HPP
  11. #include <boost/asio/associated_allocator.hpp>
  12. #include <boost/assert.hpp>
  13. #include <memory>
  14. namespace boost {
  15. namespace beast {
  16. template<class T, class Handler>
  17. void
  18. handler_ptr<T, Handler>::
  19. clear()
  20. {
  21. using A = typename detail::allocator_traits<
  22. net::associated_allocator_t<
  23. Handler>>::template rebind_alloc<T>;
  24. using alloc_traits =
  25. beast::detail::allocator_traits<A>;
  26. A alloc(
  27. net::get_associated_allocator(handler()));
  28. alloc_traits::destroy(alloc, t_);
  29. alloc_traits::deallocate(alloc, t_, 1);
  30. t_ = nullptr;
  31. }
  32. template<class T, class Handler>
  33. handler_ptr<T, Handler>::
  34. ~handler_ptr()
  35. {
  36. if(t_)
  37. {
  38. clear();
  39. h_.~Handler();
  40. }
  41. }
  42. template<class T, class Handler>
  43. handler_ptr<T, Handler>::
  44. handler_ptr(handler_ptr&& other)
  45. : t_(other.t_)
  46. {
  47. if(other.t_)
  48. {
  49. ::new(static_cast<void*>(std::addressof(h_)))
  50. Handler(std::move(other.h_));
  51. other.h_.~Handler();
  52. other.t_ = nullptr;
  53. }
  54. }
  55. template<class T, class Handler>
  56. template<class DeducedHandler, class... Args>
  57. handler_ptr<T, Handler>::
  58. handler_ptr(DeducedHandler&& h, Args&&... args)
  59. {
  60. BOOST_STATIC_ASSERT(! std::is_array<T>::value);
  61. using A = typename detail::allocator_traits<
  62. net::associated_allocator_t<
  63. Handler>>::template rebind_alloc<T>;
  64. using alloc_traits =
  65. beast::detail::allocator_traits<A>;
  66. A alloc{net::get_associated_allocator(h)};
  67. bool destroy = false;
  68. auto deleter = [&alloc, &destroy](T* p)
  69. {
  70. if(destroy)
  71. alloc_traits::destroy(alloc, p);
  72. alloc_traits::deallocate(alloc, p, 1);
  73. };
  74. std::unique_ptr<T, decltype(deleter)> t{
  75. alloc_traits::allocate(alloc, 1), deleter};
  76. alloc_traits::construct(alloc, t.get(),
  77. static_cast<DeducedHandler const&>(h),
  78. std::forward<Args>(args)...);
  79. destroy = true;
  80. ::new(static_cast<void*>(std::addressof(h_)))
  81. Handler(std::forward<DeducedHandler>(h));
  82. t_ = t.release();
  83. }
  84. template<class T, class Handler>
  85. auto
  86. handler_ptr<T, Handler>::
  87. release_handler() ->
  88. handler_type
  89. {
  90. BOOST_ASSERT(t_);
  91. clear();
  92. auto deleter = [](Handler* h)
  93. {
  94. h->~Handler();
  95. };
  96. std::unique_ptr<
  97. Handler, decltype(deleter)> destroyer{
  98. std::addressof(h_), deleter};
  99. return std::move(h_);
  100. }
  101. template<class T, class Handler>
  102. template<class... Args>
  103. void
  104. handler_ptr<T, Handler>::
  105. invoke(Args&&... args)
  106. {
  107. BOOST_ASSERT(t_);
  108. clear();
  109. auto deleter = [](Handler* h)
  110. {
  111. boost::ignore_unused(h); // fix #1119
  112. h->~Handler();
  113. };
  114. std::unique_ptr<
  115. Handler, decltype(deleter)> destroyer{
  116. std::addressof(h_), deleter};
  117. h_(std::forward<Args>(args)...);
  118. }
  119. } // beast
  120. } // boost
  121. #endif