Skip to content

Commit c6479c2

Browse files
authored
further threadsafety hardening
1 parent 6ab917a commit c6479c2

File tree

1 file changed

+12
-23
lines changed

1 file changed

+12
-23
lines changed

include/cpp-statsd-client/StatsdClient.hpp

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ class StatsdClient {
6666
const std::string& prefix,
6767
const uint64_t batchsize = 0,
6868
const uint64_t sendInterval = 1000,
69-
const int gaugePrecision = 4) noexcept;
69+
const int gaugePrecision = 4,
70+
unsigned int seed = std::random_device()()) noexcept;
7071

7172
StatsdClient(const StatsdClient&) = delete;
7273
StatsdClient& operator=(const StatsdClient&) = delete;
@@ -76,14 +77,6 @@ class StatsdClient {
7677
//!@name Methods
7778
//!@{
7879

79-
//! Sets a configuration
80-
void setConfig(const std::string& host,
81-
const uint16_t port,
82-
const std::string& prefix,
83-
const uint64_t batchsize = 0,
84-
const uint64_t sendInterval = 1000,
85-
const int gaugePrecision = 4) noexcept;
86-
8780
//! Returns the error message as an std::string
8881
const std::string& errorMessage() const noexcept;
8982

@@ -130,9 +123,6 @@ class StatsdClient {
130123
float frequency = 1.0f,
131124
const std::vector<std::string>& tags = {}) const noexcept;
132125

133-
//! Seed the RNG that controls sampling
134-
void seed(unsigned int seed = std::random_device()()) noexcept;
135-
136126
//! Flush any queued stats to the daemon
137127
void flush() noexcept;
138128

@@ -159,9 +149,6 @@ class StatsdClient {
159149
//! The UDP sender to be used for actual sending
160150
std::unique_ptr<UDPSender> m_sender;
161151

162-
//! The random number generator for handling sampling
163-
mutable std::mt19937 m_randomEngine;
164-
165152
//! Fixed floating point precision of gauges
166153
int m_gaugePrecision;
167154
};
@@ -175,6 +162,11 @@ inline std::string sanitizePrefix(std::string prefix) {
175162
return prefix;
176163
}
177164

165+
std::mt19937& rng(unsigned int seed = 0){
166+
static thread_local std::mt19937 twister(seed);
167+
return twister;
168+
}
169+
178170
// All supported metric types
179171
constexpr char METRIC_TYPE_COUNT[] = "c";
180172
constexpr char METRIC_TYPE_GAUGE[] = "g";
@@ -187,12 +179,13 @@ inline StatsdClient::StatsdClient(const std::string& host,
187179
const std::string& prefix,
188180
const uint64_t batchsize,
189181
const uint64_t sendInterval,
190-
const int gaugePrecision) noexcept
182+
const int gaugePrecision
183+
const unsigned int seed) noexcept
191184
: m_prefix(detail::sanitizePrefix(prefix)),
192185
m_sender(new UDPSender{host, port, batchsize, sendInterval}),
193186
m_gaugePrecision(gaugePrecision) {
194187
// Initialize the random generator to be used for sampling
195-
seed();
188+
rng(seed);
196189
}
197190

198191
inline void StatsdClient::setConfig(const std::string& host,
@@ -278,7 +271,7 @@ inline void StatsdClient::send(const std::string& key,
278271
const bool isFrequencyOne = std::fabs(frequency - 1.0f) < epsilon;
279272
const bool isFrequencyZero = std::fabs(frequency) < epsilon;
280273
if (isFrequencyZero ||
281-
(!isFrequencyOne && (frequency < std::uniform_real_distribution<float>(0.f, 1.f)(m_randomEngine)))) {
274+
(!isFrequencyOne && (frequency < std::uniform_real_distribution<float>(0.f, 1.f)(rng())))) {
282275
return;
283276
}
284277

@@ -321,11 +314,7 @@ inline void StatsdClient::send(const std::string& key,
321314
m_sender->send(buffer);
322315
}
323316

324-
inline void StatsdClient::seed(unsigned int seed) noexcept {
325-
m_randomEngine.seed(seed);
326-
}
327-
328-
inline void StatsdClient::flush() noexcept {
317+
inline void StatsdClient::flush() const noexcept {
329318
m_sender->flush();
330319
}
331320

0 commit comments

Comments
 (0)