Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-01 08:09:56

0001 //
0002 // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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       // embed the size at the end
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 //BOOST_DETAIL_COBALT_MAIN_HPP