transition to use boost.random instead of rand() and custom pseudo random generator

This commit is contained in:
Arvid Norberg 2014-08-16 20:26:00 +00:00
parent fcf2f6234b
commit 524384045c
19 changed files with 229 additions and 58 deletions

View File

@ -179,11 +179,13 @@ rule linking ( properties * )
result += <define>BOOST_ALL_DYN_LINK ; result += <define>BOOST_ALL_DYN_LINK ;
result += <library>/boost/system//boost_system/<link>static/<define>BOOST_ALL_DYN_LINK ; result += <library>/boost/system//boost_system/<link>static/<define>BOOST_ALL_DYN_LINK ;
result += <library>/boost/chrono//boost_chrono/<link>static/<define>BOOST_ALL_DYN_LINK ; result += <library>/boost/chrono//boost_chrono/<link>static/<define>BOOST_ALL_DYN_LINK ;
result += <library>/boost/random//boost_random/<link>static/<define>BOOST_ALL_DYN_LINK ;
} }
else else
{ {
result += <library>/boost/system//boost_system/<link>static ; result += <library>/boost/system//boost_system/<link>static ;
result += <library>/boost/chrono//boost_chrono/<link>static ; result += <library>/boost/chrono//boost_chrono/<link>static ;
result += <library>/boost/chrono//boost_random/<link>static ;
} }
if <toolset>gcc in $(properties) && <link>shared in $(properties) if <toolset>gcc in $(properties) && <link>shared in $(properties)
@ -196,6 +198,7 @@ rule linking ( properties * )
{ {
result += <library>/boost/system//boost_system/<link>shared ; result += <library>/boost/system//boost_system/<link>shared ;
result += <library>/boost/chrono//boost_chrono/<link>shared ; result += <library>/boost/chrono//boost_chrono/<link>shared ;
result += <library>/boost/chrono//boost_random/<link>shared ;
} }
result += <include>$(BOOST_ROOT) result += <include>$(BOOST_ROOT)
<define>BOOST_ALL_NO_LIB <define>BOOST_ALL_NO_LIB
@ -207,6 +210,7 @@ rule linking ( properties * )
{ {
result += <library>boost_system ; result += <library>boost_system ;
result += <library>boost_chrono ; result += <library>boost_chrono ;
result += <library>boost_random ;
# on mac the boost headers are installed in # on mac the boost headers are installed in
# a directory that isn't automatically accessable # a directory that isn't automatically accessable
@ -487,6 +491,10 @@ lib boost_chrono : : <target-os>darwin <name>boost_chrono-mt $(boost-library-sea
lib boost_chrono : : <target-os>solaris <name>boost_chrono $(boost-library-search-path) ; lib boost_chrono : : <target-os>solaris <name>boost_chrono $(boost-library-search-path) ;
lib boost_chrono : : <name>boost_chrono ; lib boost_chrono : : <name>boost_chrono ;
lib boost_random : : <target-os>darwin <name>boost_random-mt $(boost-library-search-path) ;
lib boost_random : : <target-os>solaris <name>boost_random $(boost-library-search-path) ;
lib boost_random : : <name>boost_random ;
# openssl on linux/bsd/macos etc. # openssl on linux/bsd/macos etc.
lib gcrypt : : <name>gcrypt <link>shared <search>/opt/local/lib ; lib gcrypt : : <name>gcrypt <link>shared <search>/opt/local/lib ;
lib z : : <link>shared <name>z <search>/usr/lib ; lib z : : <link>shared <name>z <search>/usr/lib ;

View File

@ -18,6 +18,6 @@ rm -f bindings/python/Makefile bindings/python/Makefile.in
chmod a-x docs/*.rst docs/*.htm* src/*.cpp include/libtorrent/*.hpp chmod a-x docs/*.rst docs/*.htm* src/*.cpp include/libtorrent/*.hpp
./autotool.sh ./autotool.sh
./configure --enable-python-binding --enable-examples=yes --enable-encryption --enable-tests=yes --with-boost-system=mt --with-boost-python=mt --enable-tests ./configure --enable-python-binding --enable-examples=yes --enable-encryption --enable-tests=yes --with-boost-system=mt --with-boost-chrono=mt --with-boost-random=mt --with-boost-python=mt --enable-tests
make V=1 -j8 check distcheck make V=1 -j8 check distcheck

View File

@ -119,12 +119,20 @@ AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
AS_ECHO AS_ECHO
AS_ECHO "Checking for boost libraries:" AS_ECHO "Checking for boost libraries:"
AX_BOOST_BASE([1.36]) AX_BOOST_BASE([1.47])
AX_BOOST_SYSTEM() AX_BOOST_SYSTEM()
AS_IF([test -z "$BOOST_SYSTEM_LIB"], AS_IF([test -z "$BOOST_SYSTEM_LIB"],
[AC_MSG_ERROR(Boost.System library not found. Try using --with-boost-system=lib)]) [AC_MSG_ERROR(Boost.System library not found. Try using --with-boost-system=lib)])
AX_BOOST_CHRONO()
AS_IF([test -z "$BOOST_CHRONO_LIB"],
[AC_MSG_ERROR(Boost.Chrono library not found. Try using --with-boost-chrono=lib)])
AX_BOOST_RANDOM()
AS_IF([test -z "$BOOST_RANDOM_LIB"],
[AC_MSG_ERROR(Boost.Random library not found. Try using --with-boost-random=lib)])
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS" CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS" LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
@ -747,6 +755,8 @@ Boost libraries:
CPPFlags: ${BOOST_CPPFLAGS} CPPFlags: ${BOOST_CPPFLAGS}
LDFlags: ${BOOST_LDFLAGS} LDFlags: ${BOOST_LDFLAGS}
boost.system: ${BOOST_SYSTEM_LIB} boost.system: ${BOOST_SYSTEM_LIB}
boost.chrono: ${BOOST_CHRONO_LIB}
boost.random: ${BOOST_RANDOM_LIB}
END END
AS_IF([test "x$ARG_ENABLE_PYTHON_BINDING" = "xyes"], [ AS_IF([test "x$ARG_ENABLE_PYTHON_BINDING" = "xyes"], [

View File

@ -1,5 +1,6 @@
example_programs = \ example_programs = \
client_test \ client_test \
stats_counters \
dump_torrent \ dump_torrent \
make_torrent \ make_torrent \
simple_client \ simple_client \

View File

@ -102,7 +102,6 @@ nobase_include_HEADERS = \
platform_util.hpp \ platform_util.hpp \
policy.hpp \ policy.hpp \
proxy_base.hpp \ proxy_base.hpp \
ptime.hpp \
puff.hpp \ puff.hpp \
random.hpp \ random.hpp \
resolver.hpp \ resolver.hpp \

View File

@ -35,6 +35,5 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent namespace libtorrent
{ {
void random_seed(boost::uint32_t v);
boost::uint32_t TORRENT_EXTRA_EXPORT random(); boost::uint32_t TORRENT_EXTRA_EXPORT random();
} }

119
m4/ax_boost_chrono.m4 Normal file
View File

@ -0,0 +1,119 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_CHRONO
#
# DESCRIPTION
#
# Test for System library from the Boost C++ libraries. The macro requires
# a preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_CHRONO_LIB)
#
# And sets:
#
# HAVE_BOOST_CHRONO
#
# LICENSE
#
# Copyright (c) 2012 Xiyue Deng <manphiz@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 1
AC_DEFUN([AX_BOOST_CHRONO],
[
AC_ARG_WITH([boost-chrono],
AS_HELP_STRING([--with-boost-chrono@<:@=special-lib@:>@],
[use the Chrono library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-chrono=boost_chrono-gcc-mt ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_chrono_lib=""
else
want_boost="yes"
ax_boost_user_chrono_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Chrono library is available,
ax_cv_boost_chrono,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/chrono.hpp>]],
[[boost::chrono::system_clock::time_point time;]])],
ax_cv_boost_chrono=yes, ax_cv_boost_chrono=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_chrono" = "xyes"; then
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_CHRONO,,[define if the Boost::Chrono library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
if test "x$ax_boost_user_chrono_lib" = "x"; then
for libextension in `ls $BOOSTLIBDIR/libboost_chrono*.so* $BOOSTLIBDIR/libboost_chrono*.dylib* $BOOSTLIBDIR/libboost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_chrono.*\)\.so.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
[link_chrono="no"])
done
if test "x$link_chrono" != "xyes"; then
for libextension in `ls $BOOSTLIBDIR/boost_chrono*.dll* $BOOSTLIBDIR/boost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_chrono.*\)\.dll.*$;\1;' -e 's;^\(boost_chrono.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
[link_chrono="no"])
done
fi
else
for ax_lib in $ax_boost_user_chrono_lib boost_chrono-$ax_boost_user_chrono_lib; do
AC_CHECK_LIB($ax_lib, exit,
[BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
[link_chrono="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_chrono" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View File

@ -44,6 +44,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert_dispatcher.hpp" #include "libtorrent/alert_dispatcher.hpp"
#include "libtorrent/performance_counters.hpp" #include "libtorrent/performance_counters.hpp"
#ifdef TORRENT_DEBUG
#include "libtorrent/random.hpp"
#endif
#if TORRENT_USE_PURGABLE_CONTROL #if TORRENT_USE_PURGABLE_CONTROL
#include <mach/mach.h> #include <mach/mach.h>
// see comments at: // see comments at:
@ -1201,7 +1205,7 @@ void block_cache::insert_blocks(cached_piece_entry* pe, int block, file::iovec_t
VM_PURGABLE_SET_STATE, VM_PURGABLE_SET_STATE,
&state); &state);
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
// if ((rand() % 200) == 0) ret = 1; // if ((random() % 200) == 0) ret = 1;
#endif #endif
if (ret != KERN_SUCCESS || (state & VM_PURGABLE_EMPTY)) if (ret != KERN_SUCCESS || (state & VM_PURGABLE_EMPTY))
{ {
@ -1250,7 +1254,7 @@ bool block_cache::inc_block_refcount(cached_piece_entry* pe, int block, int reas
VM_PURGABLE_SET_STATE, VM_PURGABLE_SET_STATE,
&state); &state);
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
// if ((rand() % 200) == 0) ret = 1; // if ((random() % 200) == 0) ret = 1;
#endif #endif
if (ret != KERN_SUCCESS || (state & VM_PURGABLE_EMPTY)) if (ret != KERN_SUCCESS || (state & VM_PURGABLE_EMPTY))
{ {
@ -1312,7 +1316,7 @@ void block_cache::dec_block_refcount(cached_piece_entry* pe, int block, int reas
VM_PURGABLE_SET_STATE, VM_PURGABLE_SET_STATE,
&state); &state);
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
// if ((rand() % 200) == 0) ret = 1; // if ((random() % 200) == 0) ret = 1;
#endif #endif
if (ret != KERN_SUCCESS || (state & VM_PURGABLE_EMPTY)) if (ret != KERN_SUCCESS || (state & VM_PURGABLE_EMPTY))
{ {

View File

@ -112,7 +112,7 @@ node_impl::node_impl(alert_dispatcher* alert_disp
, m_counters(cnt) , m_counters(cnt)
{ {
m_secret[0] = random(); m_secret[0] = random();
m_secret[1] = std::rand(); m_secret[1] = random();
} }
bool node_impl::verify_token(std::string const& token, char const* info_hash bool node_impl::verify_token(std::string const& token, char const* info_hash

View File

@ -33,40 +33,21 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/random.hpp" #include "libtorrent/random.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include <boost/random/random_device.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
namespace libtorrent namespace libtorrent
{ {
namespace
{
boost::uint32_t x = 123456789;
#ifdef TORRENT_USE_ASSERTS
bool seeded = false;
#endif
}
void random_seed(boost::uint32_t v)
{
x = v;
#ifdef TORRENT_USE_ASSERTS
seeded = true;
#endif
}
// this is an xorshift random number generator
// see: http://en.wikipedia.org/wiki/Xorshift
boost::uint32_t random() boost::uint32_t random()
{ {
TORRENT_ASSERT(seeded); using boost::random::random_device;
using boost::random::mt19937;
using boost::random::uniform_int_distribution;
static boost::uint32_t y = 362436069; static random_device dev;
static boost::uint32_t z = 521288629; static mt19937 random_engine(dev());
static boost::uint32_t w = 88675123; return uniform_int_distribution<boost::uint32_t>(0, UINT_MAX)(random_engine);
boost::uint32_t t;
t = x ^ (x << 11);
x = y; y = z; z = w;
return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
} }
} }

View File

@ -313,14 +313,6 @@ namespace aux {
} }
#endif // TORRENT_STATS #endif // TORRENT_STATS
struct seed_random_generator
{
seed_random_generator()
{
random_seed((unsigned int)((time_now().time_since_epoch().count()) & 0xffffffff));
}
};
void session_impl::init_peer_class_filter(bool unlimited_local) void session_impl::init_peer_class_filter(bool unlimited_local)
{ {
// set the default peer_class_filter to use the local peer class // set the default peer_class_filter to use the local peer class
@ -543,8 +535,6 @@ namespace aux {
TORRENT_ASSERT_VAL(!ec, ec); TORRENT_ASSERT_VAL(!ec, ec);
// ---- generate a peer id ---- // ---- generate a peer id ----
static seed_random_generator seeder;
std::string print = cl_fprint.to_string(); std::string print = cl_fprint.to_string();
TORRENT_ASSERT_VAL(print.length() <= 20, print.length()); TORRENT_ASSERT_VAL(print.length() <= 20, print.length());
@ -1852,8 +1842,8 @@ namespace aux {
{ {
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
// make it obvious that the return value is undefined // make it obvious that the return value is undefined
ret.upload_limit = rand(); ret.upload_limit = random();
ret.download_limit = rand(); ret.download_limit = random();
ret.label.resize(20); ret.label.resize(20);
url_random(&ret.label[0], &ret.label[0] + 20); url_random(&ret.label[0], &ret.label[0] + 20);
ret.ignore_unchoke_slots = false; ret.ignore_unchoke_slots = false;

View File

@ -1623,7 +1623,7 @@ namespace libtorrent
SSL_CTX_set_cert_store(ssl_ctx, cert_store); SSL_CTX_set_cert_store(ssl_ctx, cert_store);
#if 0 #if 0
char filename[100]; char filename[100];
snprintf(filename, sizeof(filename), "/tmp/%d.pem", rand()); snprintf(filename, sizeof(filename), "/tmp/%u.pem", random());
FILE* f = fopen(filename, "w+"); FILE* f = fopen(filename, "w+");
fwrite(cert.c_str(), cert.size(), 1, f); fwrite(cert.c_str(), cert.size(), 1, f);
fclose(f); fclose(f);

View File

@ -1899,7 +1899,7 @@ bool utp_socket_impl::send_pkt(int flags)
error_code ec; error_code ec;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
// simulate 1% packet loss // simulate 1% packet loss
// if ((rand() % 100) > 0) // if ((random() % 100) > 0)
#endif #endif
m_sm->send_packet(udp::endpoint(m_remote_address, m_port) m_sm->send_packet(udp::endpoint(m_remote_address, m_port)
, (char const*)h, p->size, ec , (char const*)h, p->size, ec

View File

@ -90,6 +90,7 @@ feature.compose <launcher>valgrind : <testing.launcher>"valgrind --tool=memcheck
test-suite libtorrent : test-suite libtorrent :
[ run test_socket_io.cpp ] [ run test_socket_io.cpp ]
[ run test_random.cpp ]
[ run test_utf8.cpp ] [ run test_utf8.cpp ]
[ run test_gzip.cpp ] [ run test_gzip.cpp ]
[ run test_bitfield.cpp ] [ run test_bitfield.cpp ]

View File

@ -434,8 +434,6 @@ bool get_item_cb(dht::item& i)
// TODO: 3 test obfuscated_get_peers // TODO: 3 test obfuscated_get_peers
int test_main() int test_main()
{ {
random_seed(time_now_hires().time_since_epoch().count());
dht_settings sett; dht_settings sett;
sett.max_torrents = 4; sett.max_torrents = 4;
sett.max_dht_items = 4; sett.max_dht_items = 4;

View File

@ -182,8 +182,6 @@ int test_main()
const int repcount = 128; const int repcount = 128;
#endif #endif
random_seed(time_now_hires().time_since_epoch().count());
for (int rep = 0; rep < repcount; ++rep) for (int rep = 0; rep < repcount; ++rep)
{ {
dh_key_exchange DH1, DH2; dh_key_exchange DH1, DH2;

View File

@ -271,8 +271,6 @@ int test_pick(boost::shared_ptr<piece_picker> const& p, int options = piece_pick
int test_main() int test_main()
{ {
random_seed(time_now_hires().time_since_epoch().count());
tcp::endpoint endp; tcp::endpoint endp;
piece_picker::downloading_piece st; piece_picker::downloading_piece st;
#if TORRENT_USE_ASSERTS #if TORRENT_USE_ASSERTS

View File

@ -133,8 +133,6 @@ private:
int test_main() int test_main()
{ {
random_seed(time_now_hires().time_since_epoch().count());
torrent_peer_allocator allocator; torrent_peer_allocator allocator;
external_ip ext_ip; external_ip ext_ip;

67
test/test_random.cpp Normal file
View File

@ -0,0 +1,67 @@
/*
Copyright (c) 2014, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.hpp"
#include "setup_transfer.hpp"
#include "random.hpp"
using namespace libtorrent;
int test_main()
{
const int repetitions = 200000;
for (int byte = 0; byte < 4; ++byte)
{
int buckets[256];
memset(buckets, 0, sizeof(buckets));
for (int i = 0; i < repetitions; ++i)
{
boost::uint32_t val = libtorrent::random();
val >>= byte * 8;
++buckets[val & 0xff];
}
for (int i = 0; i < 256; ++i)
{
const int expected = repetitions / 256;
// expect each bucket to be within 15% of the expected value
fprintf(stderr, "%d: %f\n", i, float(buckets[i] - expected) * 100.f / expected);
TEST_CHECK(abs(buckets[i] - expected) < expected / 6);
}
}
return 0;
}