diff --git a/CHANGELOG.md b/CHANGELOG.md index d7543651..d36417d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Version 217: * Fix file_body_win32 * Use async_initiate * Check BOOST_NO_CXX11_THREAD_LOCAL +* Fast prng is pcg -------------------------------------------------------------------------------- diff --git a/include/boost/beast/core/detail/pcg.hpp b/include/boost/beast/core/detail/pcg.hpp new file mode 100644 index 00000000..2815882a --- /dev/null +++ b/include/boost/beast/core/detail/pcg.hpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +#ifndef BOOST_BEAST_CORE_DETAIL_PCG_HPP +#define BOOST_BEAST_CORE_DETAIL_PCG_HPP + +#include +#include +#include + +namespace boost { +namespace beast { +namespace detail { + +class pcg +{ + std::uint64_t state_ = 0; + std::uint64_t increment_; + +public: + using result_type = std::uint32_t; + + // Initialize the generator. + // There are no restrictions on the input values. + pcg( + std::uint64_t seed, + std::uint64_t stream) + { + // increment must be odd + increment_ = 2 * stream + 1; + boost::ignore_unused((*this)()); + state_ += seed; + boost::ignore_unused((*this)()); + } + + std::uint32_t + operator()() + { + std::uint64_t const p = state_; + state_ = p * + 6364136223846793005ULL + + increment_; + std::uint32_t const x = + static_cast( + ((p >> 18) ^ p) >> 27); + std::uint32_t const r = p >> 59; + #ifdef BOOST_MSVC + return _rotr(x, r); + #else + return (x >> r) | (x << ((1 + ~r) & 31)); + #endif + } +}; + +} // detail +} // beast +} // boost + +#endif diff --git a/include/boost/beast/websocket/detail/impl/prng.ipp b/include/boost/beast/websocket/detail/impl/prng.ipp index 4e7eb057..e2578c41 100644 --- a/include/boost/beast/websocket/detail/impl/prng.ipp +++ b/include/boost/beast/websocket/detail/impl/prng.ipp @@ -11,6 +11,7 @@ #define BOOST_BEAST_WEBSOCKET_DETAIL_IMPL_PRNG_IPP #include +#include #include #include #include @@ -119,21 +120,25 @@ make_prng_no_tls(bool secure) class fast_prng final : public prng { int refs_ = 0; - std::minstd_rand r_; + beast::detail::pcg r_; public: fast_prng* next = nullptr; fast_prng() - : r_([] - { - static std::atomic< - std::uint64_t> nonce{0}; + : r_( + []{ auto const pv = prng_seed(); - return static_cast( - pv[0] + pv[1] + pv[2] + pv[3] + - pv[4] + pv[5] + pv[6] + pv[7] + - ++nonce); + return + ((static_cast(pv[0])<<32)+pv[1]) ^ + ((static_cast(pv[2])<<32)+pv[3]) ^ + ((static_cast(pv[4])<<32)+pv[5]) ^ + ((static_cast(pv[6])<<32)+pv[7]); + }(), + []{ + static std::atomic< + std::uint32_t> nonce{0}; + return ++nonce; }()) { } @@ -215,19 +220,23 @@ make_prng_tls(bool secure) { class fast_prng final : public prng { - std::minstd_rand r_; + beast::detail::pcg r_; public: fast_prng() - : r_([] - { - static std::atomic< - std::uint64_t> nonce{0}; + : r_( + []{ auto const pv = prng_seed(); - return static_cast( - pv[0] + pv[1] + pv[2] + pv[3] + - pv[4] + pv[5] + pv[6] + pv[7] + - ++nonce); + return + ((static_cast(pv[0])<<32)+pv[1]) ^ + ((static_cast(pv[2])<<32)+pv[3]) ^ + ((static_cast(pv[4])<<32)+pv[5]) ^ + ((static_cast(pv[6])<<32)+pv[7]); + }(), + []{ + static std::atomic< + std::uint32_t> nonce{0}; + return ++nonce; }()) { }