Skip to content

Commit f97515a

Browse files
authored
Implement random manager class (#19)
* Implement random manager class Signed-off-by: jparisu <javierparis@eprosima.com> * Add test implementation Signed-off-by: jparisu <javierparis@eprosima.com> * Add documentation Signed-off-by: jparisu <javierparis@eprosima.com> * fix windows issues Signed-off-by: jparisu <javierparis@eprosima.com> * apply suggesstions Signed-off-by: jparisu <javierparis@eprosima.com> * Add new features and test Signed-off-by: jparisu <javierparis@eprosima.com> * Implement TSafe manager Signed-off-by: jparisu <javierparis@eprosima.com> * apply suggestions Signed-off-by: jparisu <javierparis@eprosima.com> * uncrustify Signed-off-by: jparisu <javierparis@eprosima.com> * apply suggestions Signed-off-by: jparisu <javierparis@eprosima.com> Signed-off-by: jparisu <javierparis@eprosima.com>
1 parent 48cf278 commit f97515a

16 files changed

Lines changed: 1300 additions & 11 deletions
File renamed without changes.
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @file RandomManager.hpp
17+
*
18+
* This file contains class RandomManager definition.
19+
*/
20+
21+
#pragma once
22+
23+
#include <random>
24+
25+
#include <cpp_utils/library/library_dll.h>
26+
27+
namespace eprosima {
28+
namespace utils {
29+
30+
//! Data type of the random numbers generated by class \c RandomManager .
31+
using RandomNumberType = unsigned int;
32+
//! Data type of the seed.
33+
using RandomSeedType = unsigned int;
34+
35+
/**
36+
* @brief Object to manage the generation of random numbers.
37+
*
38+
* This class use different random generators from <random> library to obtain a complete random generator
39+
* with multiple features:
40+
* 1. Generate pure random numbers (no pseudorandom).
41+
* 2. Generate an always equal random sequence from a seed.
42+
* 3. Generate pseudorandom numbers from a specific seed (map each seed with always the same pseudorandom number).
43+
* These 3 features are completely independent and calls between them do not affect each other.
44+
*
45+
* Motivation: Why use this class instead of a std::rand?
46+
* The use of only rand and srand is not recommended by std (https://en.cppreference.com/w/cpp/numeric/random/rand).
47+
* Also the use of rand does not allow to create pure random numbers (it must use srand with a explicit stochastic
48+
* value as time(NULL) (that also can be repeated if executed in same second)) neither to keep state of random
49+
* sequence once a seed has been used. This means that once using rand or srand in any part of the process, the
50+
* random sequence will not be the same.
51+
* Thus, this new class allow to get pure random numbers, get pseudorandom numbers from a seed and creating
52+
* pseudorandom sequences without affecting the normal behaviour of rand and srand.
53+
*
54+
* @note This class it not thread safe.
55+
*/
56+
class RandomManager
57+
{
58+
public:
59+
60+
/**
61+
* @brief Construct a new Random Manager object.
62+
*
63+
* @param original_seed initial seed for sequence number generator.
64+
*/
65+
CPP_UTILS_DllAPI RandomManager(
66+
const RandomSeedType& original_seed = 1);
67+
68+
//! Default destructor
69+
CPP_UTILS_DllAPI ~RandomManager() = default;
70+
71+
/***********************
72+
* NATIVE METHODS
73+
***********************/
74+
/**
75+
* @brief Generate pure random number.
76+
*
77+
* Fulfill 1.
78+
* This method does not affect the sequence generation numbers.
79+
*
80+
* @return Pure random number.
81+
*/
82+
CPP_UTILS_DllAPI RandomNumberType pure_rand () noexcept;
83+
84+
/**
85+
* @brief Get next random number in pseudorandom sequence.
86+
*
87+
* Fulfill 2.
88+
*
89+
* @return Pure random number.
90+
*/
91+
CPP_UTILS_DllAPI RandomNumberType sequence_rand () noexcept;
92+
93+
//! Set seed for the sequence random series.
94+
CPP_UTILS_DllAPI void seed (
95+
const RandomSeedType& seed) noexcept;
96+
97+
/**
98+
* @brief Get a random number related with a seed.
99+
*
100+
* Fulfill 3.
101+
* This method does not affect the sequence generation numbers.
102+
* This always returns the same random number for the same seed.
103+
*
104+
* @param seed to get random number.
105+
*
106+
* @return random number seeded by \c seed .
107+
*/
108+
CPP_UTILS_DllAPI RandomNumberType seeded_rand (
109+
const RandomSeedType& seed) noexcept;
110+
111+
112+
/***********************
113+
* DERIVED METHODS
114+
***********************/
115+
// This methods only extend the API using the common word rand, but they only call native methods.
116+
117+
//! With Pure=true returns \c pure_rand . Otherwise returns \c sequence_rand .
118+
template <bool Pure = false>
119+
RandomNumberType rand () noexcept;
120+
121+
//! Return \c seeded_rand .
122+
CPP_UTILS_DllAPI RandomNumberType rand (
123+
const RandomSeedType& seed) noexcept;
124+
125+
protected:
126+
127+
//! Generation of real random numbers based on stochastic values.
128+
std::random_device pure_random_generator_;
129+
130+
//! Random generator that will not use seed (except at ctor) so always produces same random sequences.
131+
std::mt19937 std_random_generator_;
132+
133+
/**
134+
* @brief Random generator from a specific seed.
135+
*
136+
* @note using \c minstd_rand heads to seed 0 producing same value as seed 1.
137+
* Also mt is faster.
138+
*/
139+
std::mt19937 seed_random_generator_;
140+
};
141+
142+
} /* namespace utils */
143+
} /* namespace eprosima */
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @file TSafeRandomManager.hpp
17+
*
18+
* This file contains class TSafeRandomManager definition.
19+
*/
20+
21+
#pragma once
22+
23+
#include <random>
24+
25+
#include <cpp_utils/library/library_dll.h>
26+
#include <cpp_utils/math/random/RandomManager.hpp>
27+
#include <cpp_utils/types/Atomicable.hpp>
28+
#include <cpp_utils/types/Singleton.hpp>
29+
30+
namespace eprosima {
31+
namespace utils {
32+
33+
/**
34+
* @brief Object to manage the generation of random numbers in a thread environment.
35+
*
36+
* This class use different random generators from <random> library to obtain a complete random generator
37+
* with multiple features:
38+
* 1. Generate pure random numbers (no pseudorandom).
39+
* 2. Generate an always equal random sequence from a seed.
40+
* 3. Generate pseudorandom numbers from a specific seed (map each seed with always the same pseudorandom number).
41+
* These 3 features are completely independent and calls between them do not affect each other.
42+
*
43+
* Motivation: Why use this class instead of a std::rand?
44+
* The use of only rand and srand is not recommended by std (https://en.cppreference.com/w/cpp/numeric/random/rand).
45+
* Also the use of rand does not allow to create pure random numbers (it must use srand with a explicit stochastic
46+
* value as time(NULL) (that also can be repeated if executed in same second)) neither to keep state of random
47+
* sequence once a seed has been used. This means that once using rand or srand in any part of the process, the
48+
* random sequence will not be the same.
49+
* Thus, this new class allow to get pure random numbers, get pseudorandom numbers from a seed and creating
50+
* pseudorandom sequences without affecting the normal behaviour of rand and srand.
51+
*
52+
* @note this class is similar to \c RandomManager but thread-safe implementation
53+
*/
54+
class TSafeRandomManager
55+
{
56+
public:
57+
58+
/**
59+
* @brief Construct a new Random Manager object.
60+
*
61+
* @param original_seed initial seed for sequence number generator.
62+
*/
63+
CPP_UTILS_DllAPI TSafeRandomManager(
64+
const RandomSeedType& original_seed = 1);
65+
66+
//! Default destructor
67+
CPP_UTILS_DllAPI ~TSafeRandomManager() = default;
68+
69+
/***********************
70+
* NATIVE METHODS
71+
***********************/
72+
/**
73+
* @brief Generate pure random number.
74+
*
75+
* Fulfill 1.
76+
* This method does not affect the sequence generation numbers.
77+
*
78+
* @return Pure random number.
79+
*/
80+
CPP_UTILS_DllAPI RandomNumberType pure_rand () noexcept;
81+
82+
/**
83+
* @brief Get next random number in pseudorandom sequence.
84+
*
85+
* Fulfill 2.
86+
*
87+
* @return Pure random number.
88+
*/
89+
CPP_UTILS_DllAPI RandomNumberType sequence_rand () noexcept;
90+
91+
//! Set seed for the sequence random series.
92+
CPP_UTILS_DllAPI void seed (
93+
const RandomSeedType& seed) noexcept;
94+
95+
/**
96+
* @brief Get a random number related with a seed.
97+
*
98+
* Fulfill 3.
99+
* This method does not affect the sequence generation numbers.
100+
* This always returns the same random number for the same seed.
101+
*
102+
* @param seed to get random number.
103+
*
104+
* @return random number seeded by \c seed .
105+
*/
106+
CPP_UTILS_DllAPI RandomNumberType seeded_rand (
107+
const RandomSeedType& seed) noexcept;
108+
109+
110+
/***********************
111+
* DERIVED METHODS
112+
***********************/
113+
// This methods only extend the API using the common word rand, but they only call native methods.
114+
115+
//! With Pure=true returns \c pure_rand . Otherwise returns \c sequence_rand .
116+
template <bool Pure = false>
117+
RandomNumberType rand () noexcept;
118+
119+
//! Return \c seeded_rand .
120+
CPP_UTILS_DllAPI RandomNumberType rand (
121+
const RandomSeedType& seed) noexcept;
122+
123+
protected:
124+
125+
/**
126+
* @brief Generation of real random numbers based on stochastic values.
127+
*
128+
* @note this class is thread safe.
129+
*/
130+
std::random_device pure_random_generator_;
131+
132+
//! Random generator that will not use seed (except at ctor) so always produces same random sequences.
133+
Atomicable<std::mt19937> std_random_generator_;
134+
135+
//! Random generator from a specific seed.
136+
Atomicable<std::mt19937> seed_random_generator_;
137+
};
138+
139+
//! Global singleton to use a ThreadSafeRandomManager in the whole process.
140+
using GlobalRandomManager = Singleton<TSafeRandomManager, 42>;
141+
142+
} /* namespace utils */
143+
} /* namespace eprosima */

cpp_utils/include/cpp_utils/types/Atomicable.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ namespace utils {
4242
template <class Type, class Mutex = std::mutex>
4343
class Atomicable : public Type, public Mutex
4444
{
45+
using Type::Type;
4546
// Nothing to add
4647
};
4748

@@ -58,5 +59,3 @@ using SharedAtomicable = Atomicable<Type, std::shared_timed_mutex>;
5859

5960
} /* namespace utils */
6061
} /* namespace eprosima */
61-
62-
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
// limitations under the License.
1414

1515
/**
16-
* @file math.cpp
16+
* @file math_extension.cpp
1717
*
1818
*/
1919

20-
namespace eprosima {
21-
namespace utils {
22-
2320
#include <assert.h>
2421

25-
#include <cpp_utils/math/math.hpp>
22+
#include <cpp_utils/math/math_extension.hpp>
23+
24+
namespace eprosima {
25+
namespace utils {
2626

2727
bool is_even(
2828
unsigned int number) noexcept

0 commit comments

Comments
 (0)