userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
rand.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/utils/rand.hpp
4
/// @brief Random number generators
5
/// @ingroup userver_universal
6
7
#
include
<
algorithm
>
8
#
include
<
cstdint
>
9
#
include
<
limits
>
10
#
include
<
random
>
11
#
include
<
utility
>
12
13
#
include
<
userver
/
compiler
/
thread_local
.
hpp
>
14
#
include
<
userver
/
utils
/
assert
.
hpp
>
15
16
USERVER_NAMESPACE_BEGIN
17
18
namespace
utils
{
19
20
/// @brief Virtualized standard UniformRandomBitGenerator concept, for use
21
/// with random number distributions
22
class
RandomBase
{
23
public
:
24
using
result_type = uint32_t;
25
26
virtual
~RandomBase() =
default
;
27
28
virtual
result_type operator()() = 0;
29
30
static
constexpr
result_type min() {
return
std::mt19937::min(); }
31
static
constexpr
result_type max() {
return
std::mt19937::max(); }
32
};
33
34
namespace
impl {
35
36
std::seed_seq MakeSeedSeq();
37
38
class
RandomImpl
final
:
public
RandomBase
{
39
public
:
40
RandomImpl();
41
42
result_type operator()()
override
{
return
gen_(); }
43
44
private
:
45
std::mt19937 gen_;
46
};
47
48
compiler
::ThreadLocalScope<RandomImpl> UseLocalRandomImpl();
49
50
}
// namespace impl
51
52
/// @brief Calls @a func with a thread-local UniformRandomBitGenerator
53
/// (specifically of type utils::RandomBase).
54
///
55
/// @note The provided `RandomBase` instance is not cryptographically secure.
56
///
57
/// @a func should not contain any task context switches. That is, it should not
58
/// use any userver synchronization primitives and should not access
59
/// userver-based web or database clients.
60
///
61
/// @a func should not store the reference to the provided thread-local variable
62
/// for use outside of the WithThreadLocal scope.
63
///
64
/// Prefer utils::RandRange if possible.
65
///
66
/// ## Usage example
67
///
68
/// Standard distributions can be passed to WithDefaultRandom directly:
69
/// @snippet utils/rand_test.cpp WithDefaultRandom distribution
70
///
71
/// A lambda can be passed to perform a series of operations more efficiently:
72
/// @snippet utils/rand_test.cpp WithDefaultRandom multiple
73
///
74
/// @param func functor that will be invoked with the RNG
75
/// @returns The invocation result of @a func
76
template
<
typename
Func>
77
decltype
(
auto
)
WithDefaultRandom
(Func&& func) {
78
auto
random = impl::UseLocalRandomImpl();
79
return
std::forward<Func>(func)(
static_cast
<
RandomBase
&>(*random));
80
}
81
82
/// @brief Generates a random number in range [from, to)
83
/// @note The used random generator is not cryptographically secure
84
/// @note `from_inclusive` must be less than `to_exclusive`
85
template
<
typename
T>
86
T
RandRange
(T from_inclusive, T to_exclusive) {
87
UINVARIANT
(from_inclusive < to_exclusive,
"attempt to get a random value in an incorrect range"
);
88
if
constexpr
(std::is_floating_point_v<T>) {
89
return
utils
::WithDefaultRandom(std::uniform_real_distribution<T>{from_inclusive, to_exclusive});
90
}
else
{
91
// 8-bit types are not allowed in uniform_int_distribution, so increase the
92
// T size.
93
return
utils
::WithDefaultRandom(std::uniform_int_distribution<std::common_type_t<T,
unsigned
short
>>{
94
from_inclusive,
95
to_exclusive - 1
96
});
97
}
98
}
99
100
/// @brief Generates a random number in range [0, to)
101
/// @note The used random generator is not cryptographically secure
102
template
<
typename
T>
103
T
RandRange
(T to_exclusive) {
104
return
RandRange(T{0}, to_exclusive);
105
}
106
107
/// @brief Shuffles the elements within the container
108
/// @note The method used for determining a random permutation is not
109
/// cryptographically secure
110
template
<
typename
Container>
111
void
Shuffle
(Container& container) {
112
utils
::WithDefaultRandom([&container](
RandomBase
& rng) { std::ranges::shuffle(container, rng); });
113
}
114
115
/// @brief Generate a random number in the whole `uint32_t` range
116
/// @note The used random generator is not cryptographically secure
117
/// @warning Don't use `Rand() % N`, use `RandRange` instead
118
std::
uint32_t
Rand
();
119
120
}
// namespace utils
121
122
USERVER_NAMESPACE_END
userver
utils
rand.hpp
Generated on
for userver by
Doxygen
1.17.0