Nexus HTTP/3
A QUIC and HTTP/3 library
handler_ptr.hpp
1 #pragma once
2 
3 #include <memory>
4 #include <boost/asio/associated_allocator.hpp>
5 
6 namespace nexus::quic::detail {
7 
10 //
21 template <typename T, typename Handler, typename ...Args>
22 T* handler_allocate(Handler& handler, Args&& ...args)
23 {
24  using Alloc = boost::asio::associated_allocator_t<Handler>;
25  using Traits = std::allocator_traits<Alloc>;
26  using Rebind = typename Traits::template rebind_alloc<T>;
27  using RebindTraits = std::allocator_traits<Rebind>;
28  auto alloc = Rebind{boost::asio::get_associated_allocator(handler)};
29  auto p = RebindTraits::allocate(alloc, 1);
30  try {
31  RebindTraits::construct(alloc, p, std::forward<Args>(args)...);
32  return p;
33  } catch (const std::exception&) {
34  RebindTraits::deallocate(alloc, p, 1);
35  throw;
36  }
37 }
38 
52 template <typename Handler>
53 struct handler_ptr_deleter {
54  using Alloc = boost::asio::associated_allocator_t<Handler>;
55  using Traits = std::allocator_traits<Alloc>;
56 
58  Handler* handler;
59  handler_ptr_deleter(Handler* handler) noexcept : handler(handler) {}
60 
61  template <typename T>
62  void operator()(T* p) {
63  using Rebind = typename Traits::template rebind_alloc<T>;
64  using RebindTraits = std::allocator_traits<Rebind>;
65  auto alloc = Rebind{boost::asio::get_associated_allocator(*handler)};
66  RebindTraits::destroy(alloc, p);
67  RebindTraits::deallocate(alloc, p, 1);
68  }
69 };
70 
72 template <typename T, typename Handler>
73 using handler_ptr = std::unique_ptr<T, handler_ptr_deleter<Handler>>;
74 
75 } // namespace nexus::quic::detail