File indexing completed on 2025-07-01 08:09:56
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_DETAIL_COBALT_MAIN_HPP
0009 #define BOOST_DETAIL_COBALT_MAIN_HPP
0010
0011 #include <boost/cobalt/main.hpp>
0012 #include <boost/cobalt/op.hpp>
0013 #include <boost/cobalt/this_coro.hpp>
0014
0015 #include <boost/config.hpp>
0016
0017
0018 namespace boost::asio
0019 {
0020
0021 template<typename Executor>
0022 class basic_signal_set;
0023
0024 }
0025
0026 namespace boost::cobalt::detail
0027 {
0028
0029 extern "C"
0030 {
0031 int main(int argc, char * argv[]);
0032 }
0033
0034 struct signal_helper
0035 {
0036 asio::cancellation_signal signal;
0037 };
0038
0039 struct main_promise : signal_helper,
0040 promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>,
0041 promise_throw_if_cancelled_base,
0042 enable_awaitables<main_promise>,
0043 enable_await_allocator<main_promise>,
0044 enable_await_executor<main_promise>,
0045 enable_await_deferred
0046 {
0047 main_promise(int, char **) : promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>(
0048 signal_helper::signal.slot(), asio::enable_total_cancellation())
0049 {
0050 [[maybe_unused]] volatile auto p = &detail::main;
0051 }
0052
0053 #if !defined(BOOST_COBALT_NO_PMR)
0054 inline static pmr::memory_resource * my_resource = pmr::get_default_resource();
0055
0056 #if defined(__cpp_sized_deallocation)
0057 void * operator new(const std::size_t size)
0058 {
0059 return my_resource->allocate(size);
0060 }
0061
0062 void operator delete(void * raw, const std::size_t size)
0063 {
0064 return my_resource->deallocate(raw, size);
0065 }
0066 #else
0067 void * operator new(const std::size_t size)
0068 {
0069
0070 constexpr auto sz = (std::max)(alignof(std::max_align_t), sizeof(std::size_t));
0071 auto data = my_resource->allocate(size + sz);
0072
0073 return static_cast<char*>(data) + sz;
0074 }
0075
0076 void operator delete(void * data)
0077 {
0078 constexpr auto sz = (std::max)(alignof(std::max_align_t), sizeof(std::size_t));
0079 const auto size = *reinterpret_cast<std::size_t*>(static_cast<char*>(data) - sz);
0080
0081 return my_resource->deallocate(data, size);
0082 }
0083 #endif
0084
0085
0086
0087 #endif
0088 std::suspend_always initial_suspend() noexcept {return {};}
0089
0090 BOOST_COBALT_DECL
0091 auto final_suspend() noexcept -> std::suspend_never;
0092
0093 #if !defined(BOOST_NO_EXCEPTIONS)
0094 void unhandled_exception() { throw ; }
0095 #endif
0096 void return_value(int res = 0)
0097 {
0098 if (result)
0099 *result = res;
0100 }
0101
0102 friend auto ::co_main (int argc, char * argv[]) -> boost::cobalt::main;
0103 BOOST_COBALT_DECL
0104 static int run_main( ::boost::cobalt::main mn);
0105
0106 friend int main(int argc, char * argv[])
0107 {
0108 #if !defined(BOOST_COBALT_NO_PMR)
0109 pmr::unsynchronized_pool_resource root_resource;
0110 struct reset_res
0111 {
0112 void operator()(pmr::memory_resource * res)
0113 {
0114 this_thread::set_default_resource(res);
0115 }
0116 };
0117 std::unique_ptr<pmr::memory_resource, reset_res> pr{
0118 boost::cobalt::this_thread::set_default_resource(&root_resource)};
0119 char buffer[8096];
0120 pmr::monotonic_buffer_resource main_res{buffer, 8096, &root_resource};
0121 my_resource = &main_res;
0122 #endif
0123 return run_main(co_main(argc, argv));
0124 }
0125
0126 using executor_type = executor;
0127 const executor_type & get_executor() const {return *exec_;}
0128
0129 #if !defined(BOOST_COBALT_NO_PMR)
0130 using allocator_type = pmr::polymorphic_allocator<void>;
0131 using resource_type = pmr::unsynchronized_pool_resource;
0132
0133 mutable resource_type resource{my_resource};
0134 allocator_type get_allocator() const { return allocator_type(&resource); }
0135 #endif
0136
0137 using promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>::await_transform;
0138 using promise_throw_if_cancelled_base::await_transform;
0139 using enable_awaitables<main_promise>::await_transform;
0140 using enable_await_allocator<main_promise>::await_transform;
0141 using enable_await_executor<main_promise>::await_transform;
0142 using enable_await_deferred::await_transform;
0143
0144 private:
0145 int * result;
0146 std::optional<asio::executor_work_guard<executor_type>> exec;
0147 std::optional<executor_type> exec_;
0148 asio::basic_signal_set<executor_type> * signal_set;
0149 ::boost::cobalt::main get_return_object()
0150 {
0151 return ::boost::cobalt::main{this};
0152 }
0153 };
0154
0155 }
0156
0157 namespace std
0158 {
0159
0160 template<typename Char>
0161 struct coroutine_traits<boost::cobalt::main, int, Char>
0162 {
0163 using promise_type = boost::cobalt::detail::main_promise;
0164 };
0165
0166 }
0167
0168 #endif