async_base.hpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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_CORE_IMPL_ASYNC_BASE_HPP
  10. #define BOOST_BEAST_CORE_IMPL_ASYNC_BASE_HPP
  11. #include <boost/core/exchange.hpp>
  12. namespace boost {
  13. namespace beast {
  14. namespace detail {
  15. template<class State, class Allocator>
  16. struct allocate_stable_state final
  17. : stable_base
  18. , boost::empty_value<Allocator>
  19. {
  20. State value;
  21. template<class... Args>
  22. explicit
  23. allocate_stable_state(
  24. Allocator const& alloc,
  25. Args&&... args)
  26. : boost::empty_value<Allocator>(
  27. boost::empty_init_t{}, alloc)
  28. , value{std::forward<Args>(args)...}
  29. {
  30. }
  31. void destroy() override
  32. {
  33. using A = typename allocator_traits<
  34. Allocator>::template rebind_alloc<
  35. allocate_stable_state>;
  36. A a(this->get());
  37. auto* p = this;
  38. p->~allocate_stable_state();
  39. a.deallocate(p, 1);
  40. }
  41. };
  42. } // detail
  43. template<
  44. class Handler,
  45. class Executor1,
  46. class Allocator>
  47. bool
  48. asio_handler_is_continuation(
  49. async_base<Handler, Executor1, Allocator>* p)
  50. {
  51. using boost::asio::asio_handler_is_continuation;
  52. return asio_handler_is_continuation(
  53. p->get_legacy_handler_pointer());
  54. }
  55. template<
  56. class State,
  57. class Handler,
  58. class Executor1,
  59. class Allocator,
  60. class... Args>
  61. State&
  62. allocate_stable(
  63. stable_async_base<
  64. Handler, Executor1, Allocator>& base,
  65. Args&&... args)
  66. {
  67. using allocator_type = typename stable_async_base<
  68. Handler, Executor1, Allocator>::allocator_type;
  69. using state = detail::allocate_stable_state<
  70. State, allocator_type>;
  71. using A = typename detail::allocator_traits<
  72. allocator_type>::template rebind_alloc<state>;
  73. struct deleter
  74. {
  75. allocator_type alloc;
  76. state* ptr;
  77. ~deleter()
  78. {
  79. if(ptr)
  80. {
  81. A a(alloc);
  82. a.deallocate(ptr, 1);
  83. }
  84. }
  85. };
  86. A a(base.get_allocator());
  87. deleter d{base.get_allocator(), a.allocate(1)};
  88. ::new(static_cast<void*>(d.ptr))
  89. state(d.alloc, std::forward<Args>(args)...);
  90. d.ptr->next_ = base.list_;
  91. base.list_ = d.ptr;
  92. return boost::exchange(d.ptr, nullptr)->value;
  93. }
  94. } // beast
  95. } // boost
  96. #endif