File indexing completed on 2024-11-15 09:04:17
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_COBALT_RACE_HPP
0009 #define BOOST_COBALT_RACE_HPP
0010
0011 #include <boost/cobalt/concepts.hpp>
0012 #include <boost/cobalt/detail/race.hpp>
0013 #include <boost/cobalt/detail/wrapper.hpp>
0014 #include <random>
0015
0016 namespace boost::cobalt
0017 {
0018
0019 namespace detail
0020 {
0021
0022 inline std::default_random_engine &prng()
0023 {
0024 thread_local static std::default_random_engine g(std::random_device{}());
0025 return g;
0026 }
0027
0028 }
0029
0030 template<typename G>
0031 concept uniform_random_bit_generator =
0032 requires ( G & g)
0033 {
0034 {typename std::decay_t<G>::result_type() } -> std::unsigned_integral;
0035
0036 {std::decay_t<G>::min()} -> std::same_as<typename std::decay_t<G>::result_type>;
0037
0038 {std::decay_t<G>::max()} -> std::same_as<typename std::decay_t<G>::result_type>;
0039 {g()} -> std::same_as<typename std::decay_t<G>::result_type>;
0040 } && (std::decay_t<G>::max() > std::decay_t<G>::min());
0041
0042
0043
0044
0045 template<asio::cancellation_type Ct = asio::cancellation_type::all,
0046 uniform_random_bit_generator URBG,
0047 awaitable<detail::fork::promise_type> ... Promise>
0048 auto race(URBG && g, Promise && ... p) -> detail::race_variadic_impl<Ct, URBG, Promise ...>
0049 {
0050 return detail::race_variadic_impl<Ct, URBG, Promise ...>(std::forward<URBG>(g), static_cast<Promise&&>(p)...);
0051 }
0052
0053
0054 template<asio::cancellation_type Ct = asio::cancellation_type::all,
0055 uniform_random_bit_generator URBG,
0056 typename PromiseRange>
0057 requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
0058 detail::fork::promise_type>
0059 auto race(URBG && g, PromiseRange && p) -> detail::race_ranged_impl<Ct, URBG, PromiseRange>
0060 {
0061 if (std::empty(p))
0062 throw_exception(std::invalid_argument("empty range raceed"));
0063
0064 return detail::race_ranged_impl<Ct, URBG, PromiseRange>{std::forward<URBG>(g), static_cast<PromiseRange&&>(p)};
0065 }
0066
0067 template<asio::cancellation_type Ct = asio::cancellation_type::all,
0068 awaitable<detail::fork::promise_type> ... Promise>
0069 auto race(Promise && ... p) -> detail::race_variadic_impl<Ct, std::default_random_engine&, Promise ...>
0070 {
0071 return race<Ct>(detail::prng(), static_cast<Promise&&>(p)...);
0072 }
0073
0074
0075 template<asio::cancellation_type Ct = asio::cancellation_type::all, typename PromiseRange>
0076 requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
0077 detail::fork::promise_type>
0078 auto race(PromiseRange && p) -> detail::race_ranged_impl<Ct, std::default_random_engine&, PromiseRange>
0079 {
0080 if (std::empty(p))
0081 throw_exception(std::invalid_argument("empty range raceed"));
0082
0083 return race<Ct>(detail::prng(), static_cast<PromiseRange&&>(p));
0084 }
0085
0086 template<asio::cancellation_type Ct = asio::cancellation_type::all,
0087 awaitable<detail::fork::promise_type> ... Promise>
0088 auto left_race(Promise && ... p) -> detail::race_variadic_impl<Ct, detail::left_race_tag, Promise ...>
0089 {
0090 return detail::race_variadic_impl<Ct, detail::left_race_tag, Promise ...>(
0091 detail::left_race_tag{}, static_cast<Promise&&>(p)...);
0092 }
0093
0094
0095 template<asio::cancellation_type Ct = asio::cancellation_type::all, typename PromiseRange>
0096 requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
0097 detail::fork::promise_type>
0098 auto left_race(PromiseRange && p) -> detail::race_ranged_impl<Ct, detail::left_race_tag, PromiseRange>
0099 {
0100 if (std::empty(p))
0101 throw_exception(std::invalid_argument("empty range left_raceed"));
0102
0103 return detail::race_ranged_impl<Ct, detail::left_race_tag, PromiseRange>{
0104 detail::left_race_tag{}, static_cast<PromiseRange&&>(p)};
0105 }
0106
0107
0108
0109
0110 }
0111
0112 #endif