+120
-32
lines changedFilter options
+120
-32
lines changed Original file line number Diff line number Diff line change
@@ -194,22 +194,7 @@ m_bGCStatus(false),
194
194
m_ClosedSockets()
195
195
{
196
196
// Socket ID MUST start from a random value
197
-
// Note. Don't use CTimer here, because s_UDTUnited is a static instance of CUDTUnited
198
-
// with dynamic initialization (calling this constructor), while CTimer has
199
-
// a static member s_ullCPUFrequency with dynamic initialization.
200
-
// The order of initialization is not guaranteed.
201
-
timeval t;
202
-
203
-
gettimeofday(&t, 0);
204
-
srand((unsigned int)t.tv_usec);
205
-
206
-
const double rand1_0 = double(rand())/RAND_MAX;
207
-
208
-
// Motivation: in case when rand() returns the value equal to RAND_MAX,
209
-
// rand1_0 == 1, so the below formula will be
210
-
// 1 + (MAX_SOCKET_VAL-1) * 1 = 1 + MAX_SOCKET_VAL - 1 = MAX_SOCKET_VAL
211
-
// which is the highest allowed value for the socket.
212
-
m_SocketIDGenerator = 1 + int((MAX_SOCKET_VAL-1) * rand1_0);
197
+
m_SocketIDGenerator = genRandomInt(1, MAX_SOCKET_VAL);
213
198
m_SocketIDGenerator_init = m_SocketIDGenerator;
214
199
215
200
// XXX An unlikely exception thrown from the below calls
Original file line number Diff line number Diff line change
@@ -562,12 +562,6 @@ int CChannel::sendto(const sockaddr_any& addr, CPacket& packet) const
562
562
563
563
if (!packet.isControl())
564
564
{
565
-
if (dcounter == 0)
566
-
{
567
-
timeval tv;
568
-
gettimeofday(&tv, 0);
569
-
srand(tv.tv_usec & 0xFFFF);
570
-
}
571
565
++dcounter;
572
566
573
567
if (flwcounter)
@@ -581,7 +575,7 @@ int CChannel::sendto(const sockaddr_any& addr, CPacket& packet) const
581
575
if (dcounter > 8)
582
576
{
583
577
// Make a random number in the range between 8 and 24
584
-
int rnd = rand() % 16 + SRT_TEST_FAKE_LOSS;
578
+
const int rnd = srt::sync::getRandomInt(8, 24);
585
579
586
580
if (dcounter > rnd)
587
581
{
Original file line number Diff line number Diff line change
@@ -525,11 +525,9 @@ class FileCC : public SrtCongestionControlBase
525
525
526
526
m_iLastDecSeq = m_parent->sndSeqNo();
527
527
528
-
// remove global synchronization using randomization
529
-
srand(m_iLastDecSeq);
530
-
m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX));
531
-
if (m_iDecRandom < 1)
532
-
m_iDecRandom = 1;
528
+
// remove global synchronization using randomization.
529
+
m_iDecRandom = genRandomInt(1, m_iAvgNAKNum);
530
+
SRT_ASSERT(m_iDecRandom >= 1);
533
531
HLOGC(cclog.Debug, log << "FileCC: LOSS:NEW lseqno=" << lossbegin
534
532
<< ", lastsentseqno=" << m_iLastDecSeq
535
533
<< ", seqdiff=" << CSeqNo::seqoff(m_iLastDecSeq, lossbegin)
Original file line number Diff line number Diff line change
@@ -401,9 +401,7 @@ class CUDT
401
401
static int32_t generateISN()
402
402
{
403
403
using namespace srt::sync;
404
-
// Random Initial Sequence Number (normal mode)
405
-
srand((unsigned) count_microseconds(steady_clock::now().time_since_epoch()));
406
-
return (int32_t)(CSeqNo::m_iMaxSeqNo * (double(rand()) / RAND_MAX));
404
+
return genRandomInt(0, CSeqNo::m_iMaxSeqNo);
407
405
}
408
406
409
407
// For SRT_tsbpdLoop
Original file line number Diff line number Diff line change
@@ -18,11 +18,18 @@
18
18
#include "logging.h"
19
19
#include "common.h"
20
20
21
+
// HAVE_CXX11 is defined in utilities.h, included with common.h.
22
+
// The following conditional inclusion must go after common.h.
23
+
#if HAVE_CXX11
24
+
#include <random>
25
+
#endif
26
+
21
27
namespace srt_logging
22
28
{
23
29
extern Logger inlog;
24
30
}
25
31
using namespace srt_logging;
32
+
using namespace std;
26
33
27
34
namespace srt
28
35
{
@@ -267,3 +274,77 @@ bool srt::sync::CGlobEvent::waitForEvent()
267
274
return g_Sync.lock_wait_for(milliseconds_from(10));
268
275
}
269
276
277
+
////////////////////////////////////////////////////////////////////////////////
278
+
//
279
+
// Random
280
+
//
281
+
////////////////////////////////////////////////////////////////////////////////
282
+
283
+
namespace srt
284
+
{
285
+
#if HAVE_CXX11
286
+
static std::random_device& randomDevice()
287
+
{
288
+
static std::random_device s_RandomDevice;
289
+
return s_RandomDevice;
290
+
}
291
+
#elif defined(_WIN32) && defined(__MINGW32__)
292
+
static void initRandSeed()
293
+
{
294
+
const int64_t seed = sync::steady_clock::now().time_since_epoch().count();
295
+
srand((unsigned int) seed);
296
+
}
297
+
static pthread_once_t s_InitRandSeedOnce = PTHREAD_ONCE_INIT;
298
+
#else
299
+
300
+
static unsigned int genRandSeed()
301
+
{
302
+
// Duration::count() does not depend on any global objects,
303
+
// therefore it is preferred over count)microseconds(..).
304
+
const int64_t seed = sync::steady_clock::now().time_since_epoch().count();
305
+
return (unsigned int) seed;
306
+
}
307
+
308
+
static unsigned int* getRandSeed()
309
+
{
310
+
static unsigned int s_uRandSeed = genRandSeed();
311
+
return &s_uRandSeed;
312
+
}
313
+
314
+
#endif
315
+
}
316
+
317
+
int srt::sync::genRandomInt(int minVal, int maxVal)
318
+
{
319
+
// This Meyers singleton initialization is thread-safe since C++11, but is not thread-safe in C++03.
320
+
// A mutex to protect simulteneout access to the random device.
321
+
// Thread-local storage could be used here instead to store the seed / random device.
322
+
// However the generator is not used often (Initial Socket ID, Initial sequence number, FileCC),
323
+
// so sharing a single seed among threads should not impact the performance.
324
+
static sync::Mutex s_mtxRandomDevice;
325
+
sync::ScopedLock lck(s_mtxRandomDevice);
326
+
#if HAVE_CXX11
327
+
uniform_int_distribution<> dis(minVal, maxVal);
328
+
return dis(randomDevice());
329
+
#else
330
+
#if defined(__MINGW32__)
331
+
// No rand_r(..) for MinGW.
332
+
pthread_once(&s_InitRandSeedOnce, initRandSeed);
333
+
// rand() returns a pseudo-random integer in the range 0 to RAND_MAX inclusive
334
+
// (i.e., the mathematical range [0, RAND_MAX]).
335
+
// Therefore, rand_0_1 belongs to [0.0, 1.0].
336
+
const double rand_0_1 = double(rand()) / RAND_MAX;
337
+
#else // not __MINGW32__
338
+
// rand_r(..) returns a pseudo-random integer in the range 0 to RAND_MAX inclusive
339
+
// (i.e., the mathematical range [0, RAND_MAX]).
340
+
// Therefore, rand_0_1 belongs to [0.0, 1.0].
341
+
const double rand_0_1 = double(rand_r(getRandSeed())) / RAND_MAX;
342
+
#endif
343
+
344
+
// Map onto [minVal, maxVal].
345
+
// Note. The probablity to get maxVal as the result is minuscule.
346
+
const int res = minVal + static_cast<int>((maxVal - minVal) * rand_0_1);
347
+
return res;
348
+
#endif // HAVE_CXX11
349
+
}
350
+
Original file line number Diff line number Diff line change
@@ -835,6 +835,18 @@ void SetThreadLocalError(const CUDTException& e);
835
835
/// @returns CUDTException pointer
836
836
CUDTException& GetThreadLocalError();
837
837
838
+
////////////////////////////////////////////////////////////////////////////////
839
+
//
840
+
// Random distribution functions.
841
+
//
842
+
////////////////////////////////////////////////////////////////////////////////
843
+
844
+
/// Generate a uniform-distributed random integer from [minVal; maxVal].
845
+
/// If HAVE_CXX11, uses std::uniform_distribution(std::random_device).
846
+
/// @param[in] minVal minimum allowed value of the resulting random number.
847
+
/// @param[in] maxVal maximum allowed value of the resulting random number.
848
+
int genRandomInt(int minVal, int maxVal);
849
+
838
850
} // namespace sync
839
851
} // namespace srt
840
852
Original file line number Diff line number Diff line change
@@ -34,7 +34,6 @@ written by
34
34
#define ATR_UNUSED
35
35
#define ATR_DEPRECATED
36
36
#endif
37
-
38
37
#if defined(__cplusplus) && __cplusplus > 199711L
39
38
#define HAVE_CXX11 1
40
39
Original file line number Diff line number Diff line change
@@ -157,6 +157,27 @@ TEST(SyncDuration, OperatorMultIntEq)
157
157
EXPECT_EQ(count_milliseconds(a), 7000);
158
158
}
159
159
160
+
TEST(SyncRandom, GenRandomInt)
161
+
{
162
+
vector<int> mn(64);
163
+
164
+
for (int i = 0; i < 2048; ++i)
165
+
{
166
+
const int rand_val = genRandomInt(0, 63);
167
+
ASSERT_GE(rand_val, 0);
168
+
ASSERT_LE(rand_val, 63);
169
+
++mn[rand_val];
170
+
}
171
+
172
+
// Uncomment to see the distribution.
173
+
// for (size_t i = 0; i < mn.size(); ++i)
174
+
// {
175
+
// cout << i << '\t';
176
+
// for (int j=0; j<mn[i]; ++j) cout << '*';
177
+
// cout << '\n';
178
+
// }
179
+
}
180
+
160
181
/*****************************************************************************/
161
182
/*
162
183
* TimePoint tests
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4