Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:44:27

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_COBALT_WITH_HPP
0009 #define BOOST_COBALT_WITH_HPP
0010 
0011 #include <exception>
0012 #include <utility>
0013 #include <boost/cobalt/detail/util.hpp>
0014 #include <boost/cobalt/detail/await_result_helper.hpp>
0015 #include <boost/cobalt/detail/with.hpp>
0016 
0017 
0018 namespace boost::cobalt
0019 {
0020 
0021 namespace detail
0022 {
0023 
0024 template<typename T>
0025 auto invoke_await_exit(T && t, std::exception_ptr & e)
0026 {
0027   return std::forward<T>(t).await_exit(e);
0028 }
0029 
0030 }
0031 
0032 
0033 template<typename Arg, typename Func, typename Teardown>
0034     requires (requires (Func func, Arg & arg, Teardown & teardown, std::exception_ptr ep)
0035     {
0036         {std::move(func)(arg)} -> awaitable<detail::with_impl<void>::promise_type>;
0037         {std::move(teardown)(std::move(arg), ep)} -> awaitable<detail::with_impl<void>::promise_type>;
0038         {std::declval<detail::co_await_result_t<decltype(std::move(func)(arg))>>()} -> std::same_as<void>;
0039     })
0040 auto with(Arg arg, Func func, Teardown teardown) -> detail::with_impl<void>
0041 {
0042 
0043     std::exception_ptr e;
0044 #if defined(BOOST_NO_EXCEPTIONS)
0045     co_await std::move(func)(arg);
0046     co_await std::move(teardown)(arg, e);
0047 #else
0048     try
0049     {
0050         co_await std::move(func)(arg);
0051     }
0052     catch (...)
0053     {
0054         e = std::current_exception();
0055     }
0056 
0057     try
0058     {
0059         co_await std::move(teardown)(std::move(arg), e);
0060     }
0061     catch (...)
0062     {
0063         if (!e)
0064             e = std::current_exception();
0065     }
0066     if (e)
0067         std::rethrow_exception(e);
0068 #endif
0069 }
0070 
0071 
0072 template<typename Arg, typename Func, typename Teardown>
0073     requires (requires (Func func, Arg & arg, Teardown & teardown, std::exception_ptr e)
0074     {
0075         {std::move(teardown)(std::move(arg), e)} -> awaitable<detail::with_impl<void>::promise_type>;
0076         {std::move(func)(arg)} -> std::same_as<void>;
0077     }
0078     && (!requires (Func func, Arg & arg)
0079     {
0080         {std::move(func)(arg)} -> awaitable<detail::with_impl<void>::promise_type>;
0081     }))
0082 auto with(Arg arg, Func func, Teardown teardown) -> detail::with_impl<void>
0083 {
0084     std::exception_ptr e;
0085 #if defined(BOOST_NO_EXCEPTIONS)
0086     std::move(func)(arg);
0087     co_await std::move(teardown)(arg, e);
0088 #else
0089     try
0090     {
0091         std::move(func)(arg);
0092     }
0093     catch (...)
0094     {
0095         e = std::current_exception();
0096     }
0097 
0098     try
0099     {
0100         co_await std::move(teardown)(arg, e);
0101     }
0102     catch (...)
0103     {
0104         if (!e)
0105             e = std::current_exception();
0106     }
0107     if (e)
0108         std::rethrow_exception(e);
0109 #endif
0110 }
0111 
0112 
0113 template<typename Arg, typename Func, typename Teardown>
0114     requires (requires (Func func, Arg & arg, Teardown & teardown, std::exception_ptr ep)
0115     {
0116         {std::move(func)(arg)} -> awaitable<detail::with_impl<void>::promise_type>;
0117         {std::move(teardown)(std::move(arg), ep)} -> awaitable<detail::with_impl<void>::promise_type>;
0118         {std::declval<detail::co_await_result_t<decltype(std::move(func)(arg))>>()} -> std::move_constructible;
0119     })
0120 auto with(Arg arg, Func func, Teardown teardown)
0121     -> detail::with_impl<detail::co_await_result_t<decltype(std::move(func)(arg))>>
0122 {
0123     std::exception_ptr e;
0124     std::optional<detail::co_await_result_t<decltype(std::move(func)(arg))>> res;
0125 
0126 #if defined(BOOST_NO_EXCEPTIONS)
0127     res = co_await std::move(func)(arg);
0128     co_await std::move(teardown)(std::move(arg), e);
0129 #else
0130     try
0131     {
0132         res = co_await std::move(func)(arg);
0133     }
0134     catch (...)
0135     {
0136         e = std::current_exception();
0137     }
0138 
0139     try
0140     {
0141         co_await std::move(teardown)(std::move(arg), e);
0142     }
0143     catch (...)
0144     {
0145         if (!e)
0146             e = std::current_exception();
0147     }
0148     if (e)
0149         std::rethrow_exception(e);
0150 #endif
0151     co_return std::move(res);
0152 }
0153 
0154 
0155 template<typename Arg, typename Func, typename Teardown>
0156     requires (requires (Func func, Arg & arg, Teardown & teardown, std::exception_ptr e)
0157     {
0158         {std::move(teardown)(std::move(arg), e)} -> awaitable<detail::with_impl<void>::promise_type>;
0159         {std::move(func)(arg)} -> std::move_constructible;
0160     }
0161     && (!requires (Func func, Arg & arg)
0162     {
0163         {std::move(func)(arg)} -> awaitable<detail::with_impl<void>::promise_type>;
0164     }))
0165 auto with(Arg arg, Func func, Teardown teardown) -> detail::with_impl<decltype(std::move(func)(arg))>
0166 {
0167     std::exception_ptr e;
0168     std::optional<decltype(std::move(func)(arg))> res;
0169 
0170 #if defined(BOOST_NO_EXCEPTIONS)
0171     res = std::move(func)(arg);
0172     co_await std::move(teardown)(arg, e);
0173 #else
0174     try
0175     {
0176       res = std::move(func)(arg);
0177     }
0178     catch (...)
0179     {
0180         e = std::current_exception();
0181     }
0182 
0183     try
0184     {
0185         co_await std::move(teardown)(arg, e);
0186     }
0187     catch (...)
0188     {
0189         if (!e)
0190             e = std::current_exception();
0191     }
0192     if (e)
0193         std::rethrow_exception(e);
0194 #endif
0195     co_return std::move(res);
0196 }
0197 
0198 
0199 
0200 template<typename Arg, typename Func>
0201   requires requires  (Arg args, std::exception_ptr ep)
0202   {
0203     {std::move(args).await_exit(ep)} -> awaitable<detail::with_impl<void>::promise_type>;
0204   }
0205 auto with(Arg && arg, Func && func)
0206 {
0207   return with(std::forward<Arg>(arg), std::forward<Func>(func), &detail::invoke_await_exit<Arg>);
0208 }
0209 
0210 }
0211 
0212 
0213 #endif //BOOST_COBALT_WITH_HPP