123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- //
- // Copyright (c) 2022 Klemens Morgenstern ([email protected])
- //
- // 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_COBALT_RACE_HPP
- #define BOOST_COBALT_RACE_HPP
- #include <boost/cobalt/concepts.hpp>
- #include <boost/cobalt/detail/race.hpp>
- #include <boost/cobalt/detail/wrapper.hpp>
- #include <random>
- namespace boost::cobalt
- {
- namespace detail
- {
- inline std::default_random_engine &prng()
- {
- thread_local static std::default_random_engine g(std::random_device{}());
- return g;
- }
- }
- // tag::concept[]
- template<typename G>
- concept uniform_random_bit_generator =
- requires ( G & g)
- {
- {typename std::decay_t<G>::result_type() } -> std::unsigned_integral; // is an unsigned integer type
- // T Returns the smallest value that G's operator() may return. The value is strictly less than G::max(). The function must be constexpr.
- {std::decay_t<G>::min()} -> std::same_as<typename std::decay_t<G>::result_type>;
- // T Returns the largest value that G's operator() may return. The value is strictly greater than G::min(). The function must be constexpr.
- {std::decay_t<G>::max()} -> std::same_as<typename std::decay_t<G>::result_type>;
- {g()} -> std::same_as<typename std::decay_t<G>::result_type>;
- } && (std::decay_t<G>::max() > std::decay_t<G>::min());
- // end::concept[]
- template<asio::cancellation_type Ct = asio::cancellation_type::all,
- uniform_random_bit_generator URBG,
- awaitable<detail::fork::promise_type> ... Promise>
- auto race(URBG && g, Promise && ... p) -> detail::race_variadic_impl<Ct, URBG, Promise ...>
- {
- return detail::race_variadic_impl<Ct, URBG, Promise ...>(std::forward<URBG>(g), static_cast<Promise&&>(p)...);
- }
- template<asio::cancellation_type Ct = asio::cancellation_type::all,
- uniform_random_bit_generator URBG,
- typename PromiseRange>
- requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
- detail::fork::promise_type>
- auto race(URBG && g, PromiseRange && p) -> detail::race_ranged_impl<Ct, URBG, PromiseRange>
- {
- if (std::empty(p))
- throw_exception(std::invalid_argument("empty range raceed"));
- return detail::race_ranged_impl<Ct, URBG, PromiseRange>{std::forward<URBG>(g), static_cast<PromiseRange&&>(p)};
- }
- template<asio::cancellation_type Ct = asio::cancellation_type::all,
- awaitable<detail::fork::promise_type> ... Promise>
- auto race(Promise && ... p) -> detail::race_variadic_impl<Ct, std::default_random_engine&, Promise ...>
- {
- return race<Ct>(detail::prng(), static_cast<Promise&&>(p)...);
- }
- template<asio::cancellation_type Ct = asio::cancellation_type::all, typename PromiseRange>
- requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
- detail::fork::promise_type>
- auto race(PromiseRange && p) -> detail::race_ranged_impl<Ct, std::default_random_engine&, PromiseRange>
- {
- if (std::empty(p))
- throw_exception(std::invalid_argument("empty range raceed"));
- return race<Ct>(detail::prng(), static_cast<PromiseRange&&>(p));
- }
- template<asio::cancellation_type Ct = asio::cancellation_type::all,
- awaitable<detail::fork::promise_type> ... Promise>
- auto left_race(Promise && ... p) -> detail::race_variadic_impl<Ct, detail::left_race_tag, Promise ...>
- {
- return detail::race_variadic_impl<Ct, detail::left_race_tag, Promise ...>(
- detail::left_race_tag{}, static_cast<Promise&&>(p)...);
- }
- template<asio::cancellation_type Ct = asio::cancellation_type::all, typename PromiseRange>
- requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
- detail::fork::promise_type>
- auto left_race(PromiseRange && p) -> detail::race_ranged_impl<Ct, detail::left_race_tag, PromiseRange>
- {
- if (std::empty(p))
- throw_exception(std::invalid_argument("empty range left_raceed"));
- return detail::race_ranged_impl<Ct, detail::left_race_tag, PromiseRange>{
- detail::left_race_tag{}, static_cast<PromiseRange&&>(p)};
- }
- }
- #endif //BOOST_COBALT_RACE_HPP
|