main.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. //
  2. // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
  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. #ifndef BOOST_DETAIL_COBALT_MAIN_HPP
  8. #define BOOST_DETAIL_COBALT_MAIN_HPP
  9. #include <boost/cobalt/main.hpp>
  10. #include <boost/cobalt/this_coro.hpp>
  11. #include <boost/config.hpp>
  12. namespace boost::asio
  13. {
  14. template<typename Executor>
  15. class basic_signal_set;
  16. }
  17. namespace boost::cobalt::detail
  18. {
  19. extern "C"
  20. {
  21. int main(int argc, char * argv[]);
  22. }
  23. struct signal_helper
  24. {
  25. asio::cancellation_signal signal;
  26. };
  27. struct main_promise : signal_helper,
  28. promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>,
  29. promise_throw_if_cancelled_base,
  30. enable_awaitables<main_promise>,
  31. enable_await_allocator<main_promise>,
  32. enable_await_executor<main_promise>
  33. {
  34. main_promise(int, char **) : promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>(
  35. signal_helper::signal.slot(), asio::enable_total_cancellation())
  36. {
  37. [[maybe_unused]] volatile auto p = &detail::main;
  38. }
  39. #if !defined(BOOST_COBALT_NO_PMR)
  40. inline static pmr::memory_resource * my_resource = pmr::get_default_resource();
  41. void * operator new(const std::size_t size)
  42. {
  43. return my_resource->allocate(size);
  44. }
  45. void operator delete(void * raw, const std::size_t size)
  46. {
  47. return my_resource->deallocate(raw, size);
  48. }
  49. #endif
  50. std::suspend_always initial_suspend() {return {};}
  51. BOOST_COBALT_DECL
  52. auto final_suspend() noexcept -> std::suspend_never;
  53. void unhandled_exception() { throw ; }
  54. void return_value(int res = 0)
  55. {
  56. if (result)
  57. *result = res;
  58. }
  59. friend auto ::co_main (int argc, char * argv[]) -> boost::cobalt::main;
  60. BOOST_COBALT_DECL
  61. static int run_main( ::boost::cobalt::main mn);
  62. friend int main(int argc, char * argv[])
  63. {
  64. #if !defined(BOOST_COBALT_NO_PMR)
  65. pmr::unsynchronized_pool_resource root_resource;
  66. struct reset_res
  67. {
  68. void operator()(pmr::memory_resource * res)
  69. {
  70. this_thread::set_default_resource(res);
  71. }
  72. };
  73. std::unique_ptr<pmr::memory_resource, reset_res> pr{
  74. boost::cobalt::this_thread::set_default_resource(&root_resource)};
  75. char buffer[8096];
  76. pmr::monotonic_buffer_resource main_res{buffer, 8096, &root_resource};
  77. my_resource = &main_res;
  78. #endif
  79. return run_main(co_main(argc, argv));
  80. }
  81. using executor_type = executor;
  82. const executor_type & get_executor() const {return *exec_;}
  83. #if !defined(BOOST_COBALT_NO_PMR)
  84. using allocator_type = pmr::polymorphic_allocator<void>;
  85. using resource_type = pmr::unsynchronized_pool_resource;
  86. mutable resource_type resource{my_resource};
  87. allocator_type get_allocator() const { return allocator_type(&resource); }
  88. #endif
  89. using promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>::await_transform;
  90. using promise_throw_if_cancelled_base::await_transform;
  91. using enable_awaitables<main_promise>::await_transform;
  92. using enable_await_allocator<main_promise>::await_transform;
  93. using enable_await_executor<main_promise>::await_transform;
  94. private:
  95. int * result;
  96. std::optional<asio::executor_work_guard<executor_type>> exec;
  97. std::optional<executor_type> exec_;
  98. asio::basic_signal_set<executor_type> * signal_set;
  99. ::boost::cobalt::main get_return_object()
  100. {
  101. return ::boost::cobalt::main{this};
  102. }
  103. };
  104. }
  105. namespace std
  106. {
  107. template<typename Char>
  108. struct coroutine_traits<boost::cobalt::main, int, Char>
  109. {
  110. using promise_type = boost::cobalt::detail::main_promise;
  111. };
  112. }
  113. #endif //BOOST_DETAIL_COBALT_MAIN_HPP