123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- //
- // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- #ifndef BOOST_DETAIL_COBALT_MAIN_HPP
- #define BOOST_DETAIL_COBALT_MAIN_HPP
- #include <boost/cobalt/main.hpp>
- #include <boost/cobalt/op.hpp>
- #include <boost/cobalt/this_coro.hpp>
- #include <boost/config.hpp>
- namespace boost::asio
- {
- template<typename Executor>
- class basic_signal_set;
- }
- namespace boost::cobalt::detail
- {
- extern "C"
- {
- int main(int argc, char * argv[]);
- }
- struct signal_helper
- {
- asio::cancellation_signal signal;
- };
- struct main_promise : signal_helper,
- promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>,
- promise_throw_if_cancelled_base,
- enable_awaitables<main_promise>,
- enable_await_allocator<main_promise>,
- enable_await_executor<main_promise>,
- enable_await_deferred
- {
- main_promise(int, char **) : promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>(
- signal_helper::signal.slot(), asio::enable_total_cancellation())
- {
- [[maybe_unused]] volatile auto p = &detail::main;
- }
- #if !defined(BOOST_COBALT_NO_PMR)
- inline static pmr::memory_resource * my_resource = pmr::get_default_resource();
- #if defined(__cpp_sized_deallocation)
- void * operator new(const std::size_t size)
- {
- return my_resource->allocate(size);
- }
- void operator delete(void * raw, const std::size_t size)
- {
- return my_resource->deallocate(raw, size);
- }
- #else
- void * operator new(const std::size_t size)
- {
- // embed the size at the end
- constexpr auto sz = (std::max)(alignof(std::max_align_t), sizeof(std::size_t));
- auto data = my_resource->allocate(size + sz);
- return static_cast<char*>(data) + sz;
- }
- void operator delete(void * data)
- {
- constexpr auto sz = (std::max)(alignof(std::max_align_t), sizeof(std::size_t));
- const auto size = *reinterpret_cast<std::size_t*>(static_cast<char*>(data) - sz);
- return my_resource->deallocate(data, size);
- }
- #endif
- #endif
- std::suspend_always initial_suspend() noexcept {return {};}
- BOOST_COBALT_DECL
- auto final_suspend() noexcept -> std::suspend_never;
- #if !defined(BOOST_NO_EXCEPTIONS)
- void unhandled_exception() { throw ; }
- #endif
- void return_value(int res = 0)
- {
- if (result)
- *result = res;
- }
- friend auto ::co_main (int argc, char * argv[]) -> boost::cobalt::main;
- BOOST_COBALT_DECL
- static int run_main( ::boost::cobalt::main mn);
- friend int main(int argc, char * argv[])
- {
- #if !defined(BOOST_COBALT_NO_PMR)
- pmr::unsynchronized_pool_resource root_resource;
- struct reset_res
- {
- void operator()(pmr::memory_resource * res)
- {
- this_thread::set_default_resource(res);
- }
- };
- std::unique_ptr<pmr::memory_resource, reset_res> pr{
- boost::cobalt::this_thread::set_default_resource(&root_resource)};
- char buffer[8096];
- pmr::monotonic_buffer_resource main_res{buffer, 8096, &root_resource};
- my_resource = &main_res;
- #endif
- return run_main(co_main(argc, argv));
- }
- using executor_type = executor;
- const executor_type & get_executor() const {return *exec_;}
- #if !defined(BOOST_COBALT_NO_PMR)
- using allocator_type = pmr::polymorphic_allocator<void>;
- using resource_type = pmr::unsynchronized_pool_resource;
- mutable resource_type resource{my_resource};
- allocator_type get_allocator() const { return allocator_type(&resource); }
- #endif
- using promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>::await_transform;
- using promise_throw_if_cancelled_base::await_transform;
- using enable_awaitables<main_promise>::await_transform;
- using enable_await_allocator<main_promise>::await_transform;
- using enable_await_executor<main_promise>::await_transform;
- using enable_await_deferred::await_transform;
- private:
- int * result;
- std::optional<asio::executor_work_guard<executor_type>> exec;
- std::optional<executor_type> exec_;
- asio::basic_signal_set<executor_type> * signal_set;
- ::boost::cobalt::main get_return_object()
- {
- return ::boost::cobalt::main{this};
- }
- };
- }
- namespace std
- {
- template<typename Char>
- struct coroutine_traits<boost::cobalt::main, int, Char>
- {
- using promise_type = boost::cobalt::detail::main_promise;
- };
- }
- #endif //BOOST_DETAIL_COBALT_MAIN_HPP
|