execution_context.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //
  2. // impl/execution_context.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_IMPL_EXECUTION_CONTEXT_HPP
  11. #define BOOST_ASIO_IMPL_EXECUTION_CONTEXT_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <cstring>
  16. #include <boost/asio/detail/handler_type_requirements.hpp>
  17. #include <boost/asio/detail/memory.hpp>
  18. #include <boost/asio/detail/service_registry.hpp>
  19. #include <boost/asio/detail/throw_exception.hpp>
  20. #include <boost/asio/detail/push_options.hpp>
  21. namespace boost {
  22. namespace asio {
  23. template <typename Allocator>
  24. execution_context::execution_context(allocator_arg_t, const Allocator& a)
  25. : execution_context(detail::allocate_object<allocator_impl<Allocator>>(a, a))
  26. {
  27. }
  28. template <typename Allocator>
  29. execution_context::execution_context(allocator_arg_t, const Allocator& a,
  30. const service_maker& initial_services)
  31. : execution_context(detail::allocate_object<allocator_impl<Allocator>>(a, a),
  32. initial_services)
  33. {
  34. }
  35. inline execution_context::auto_allocator_ptr::~auto_allocator_ptr()
  36. {
  37. ptr_->destroy();
  38. }
  39. template <typename Allocator>
  40. void execution_context::allocator_impl<Allocator>::destroy()
  41. {
  42. detail::deallocate_object(allocator_, this);
  43. }
  44. template <typename Allocator>
  45. void* execution_context::allocator_impl<Allocator>::allocate(
  46. std::size_t size, std::size_t align)
  47. {
  48. typename std::allocator_traits<Allocator>::template
  49. rebind_alloc<unsigned char> alloc(allocator_);
  50. std::size_t space = size + align - 1;
  51. unsigned char* base = std::allocator_traits<decltype(alloc)>::allocate(
  52. alloc, space + sizeof(std::ptrdiff_t));
  53. void* p = base;
  54. if (detail::align(align, size, p, space))
  55. {
  56. std::ptrdiff_t off = static_cast<unsigned char*>(p) - base;
  57. std::memcpy(static_cast<unsigned char*>(p) + size, &off, sizeof(off));
  58. return p;
  59. }
  60. std::bad_alloc ex;
  61. boost::asio::detail::throw_exception(ex);
  62. return 0;
  63. }
  64. template <typename Allocator>
  65. void execution_context::allocator_impl<Allocator>::deallocate(
  66. void* ptr, std::size_t size, std::size_t align)
  67. {
  68. if (ptr)
  69. {
  70. typename std::allocator_traits<Allocator>::template
  71. rebind_alloc<unsigned char> alloc(allocator_);
  72. std::ptrdiff_t off;
  73. std::memcpy(&off, static_cast<unsigned char*>(ptr) + size, sizeof(off));
  74. unsigned char* base = static_cast<unsigned char*>(ptr) - off;
  75. std::allocator_traits<decltype(alloc)>::deallocate(
  76. alloc, base, size + align - 1 + sizeof(std::ptrdiff_t));
  77. }
  78. }
  79. #if !defined(GENERATING_DOCUMENTATION)
  80. template <typename Service>
  81. inline Service& use_service(execution_context& e)
  82. {
  83. // Check that Service meets the necessary type requirements.
  84. (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
  85. return e.service_registry_->template use_service<Service>();
  86. }
  87. template <typename Service, typename... Args>
  88. Service& make_service(execution_context& e, Args&&... args)
  89. {
  90. // Check that Service meets the necessary type requirements.
  91. (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
  92. return e.service_registry_->template make_service<Service>(
  93. static_cast<Args&&>(args)...);
  94. }
  95. template <typename Service>
  96. BOOST_ASIO_DEPRECATED_MSG("Use make_service()")
  97. inline void add_service(execution_context& e, Service* svc)
  98. {
  99. // Check that Service meets the necessary type requirements.
  100. (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
  101. e.service_registry_->template add_service<Service>(svc);
  102. }
  103. template <typename Service>
  104. inline bool has_service(execution_context& e)
  105. {
  106. // Check that Service meets the necessary type requirements.
  107. (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
  108. return e.service_registry_->template has_service<Service>();
  109. }
  110. #endif // !defined(GENERATING_DOCUMENTATION)
  111. inline execution_context& execution_context::service::context()
  112. {
  113. return owner_;
  114. }
  115. } // namespace asio
  116. } // namespace boost
  117. #include <boost/asio/detail/pop_options.hpp>
  118. #endif // BOOST_ASIO_IMPL_EXECUTION_CONTEXT_HPP