1//
2// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8#ifndef BOOST_COBALT_RACE_HPP
9#define BOOST_COBALT_RACE_HPP
10
11#include <boost/cobalt/concepts.hpp>
12#include <boost/cobalt/detail/race.hpp>
13#include <boost/cobalt/detail/wrapper.hpp>
14#include <random>
15
16namespace boost::cobalt
17{
18
19namespace detail
20{
21
22inline std::default_random_engine &prng()
23{
24 thread_local static std::default_random_engine g(std::random_device{}());
25 return g;
26}
27
28}
29// tag::concept[]
30template<typename G>
31 concept uniform_random_bit_generator =
32 requires ( G & g)
33 {
34 {typename std::decay_t<G>::result_type() } -> std::unsigned_integral; // is an unsigned integer type
35 // T Returns the smallest value that G's operator() may return. The value is strictly less than G::max(). The function must be constexpr.
36 {std::decay_t<G>::min()} -> std::same_as<typename std::decay_t<G>::result_type>;
37 // T Returns the largest value that G's operator() may return. The value is strictly greater than G::min(). The function must be constexpr.
38 {std::decay_t<G>::max()} -> std::same_as<typename std::decay_t<G>::result_type>;
39 {g()} -> std::same_as<typename std::decay_t<G>::result_type>;
40 } && (std::decay_t<G>::max() > std::decay_t<G>::min());
41
42// end::concept[]
43
44
45template<asio::cancellation_type Ct = asio::cancellation_type::all,
46 uniform_random_bit_generator URBG,
47 awaitable<detail::fork::promise_type> ... Promise>
48auto race(URBG && g, Promise && ... p) -> detail::race_variadic_impl<Ct, URBG, Promise ...>
49{
50 return detail::race_variadic_impl<Ct, URBG, Promise ...>(std::forward<URBG>(g), static_cast<Promise&&>(p)...);
51}
52
53
54template<asio::cancellation_type Ct = asio::cancellation_type::all,
55 uniform_random_bit_generator URBG,
56 typename PromiseRange>
57requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
58 detail::fork::promise_type>
59auto race(URBG && g, PromiseRange && p) -> detail::race_ranged_impl<Ct, URBG, PromiseRange>
60{
61 if (std::empty(p))
62 throw_exception(e: std::invalid_argument("empty range raceed"));
63
64 return detail::race_ranged_impl<Ct, URBG, PromiseRange>{std::forward<URBG>(g), static_cast<PromiseRange&&>(p)};
65}
66
67template<asio::cancellation_type Ct = asio::cancellation_type::all,
68 awaitable<detail::fork::promise_type> ... Promise>
69auto race(Promise && ... p) -> detail::race_variadic_impl<Ct, std::default_random_engine&, Promise ...>
70{
71 return race<Ct>(detail::prng(), static_cast<Promise&&>(p)...);
72}
73
74
75template<asio::cancellation_type Ct = asio::cancellation_type::all, typename PromiseRange>
76 requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
77 detail::fork::promise_type>
78auto race(PromiseRange && p) -> detail::race_ranged_impl<Ct, std::default_random_engine&, PromiseRange>
79{
80 if (std::empty(p))
81 throw_exception(e: std::invalid_argument("empty range raceed"));
82
83 return race<Ct>(detail::prng(), static_cast<PromiseRange&&>(p));
84}
85
86template<asio::cancellation_type Ct = asio::cancellation_type::all,
87 awaitable<detail::fork::promise_type> ... Promise>
88auto left_race(Promise && ... p) -> detail::race_variadic_impl<Ct, detail::left_race_tag, Promise ...>
89{
90 return detail::race_variadic_impl<Ct, detail::left_race_tag, Promise ...>(
91 detail::left_race_tag{}, static_cast<Promise&&>(p)...);
92}
93
94
95template<asio::cancellation_type Ct = asio::cancellation_type::all, typename PromiseRange>
96requires awaitable<std::decay_t<decltype(*std::declval<PromiseRange>().begin())>,
97 detail::fork::promise_type>
98auto left_race(PromiseRange && p) -> detail::race_ranged_impl<Ct, detail::left_race_tag, PromiseRange>
99{
100 if (std::empty(p))
101 throw_exception(e: std::invalid_argument("empty range left_raceed"));
102
103 return detail::race_ranged_impl<Ct, detail::left_race_tag, PromiseRange>{
104 detail::left_race_tag{}, static_cast<PromiseRange&&>(p)};
105}
106
107
108
109
110}
111
112#endif //BOOST_COBALT_RACE_HPP
113

source code of boost/libs/cobalt/include/boost/cobalt/race.hpp