diff options
Diffstat (limited to 'boost/beast/websocket/detail/prng.ipp')
-rw-r--r-- | boost/beast/websocket/detail/prng.ipp | 294 |
1 files changed, 59 insertions, 235 deletions
diff --git a/boost/beast/websocket/detail/prng.ipp b/boost/beast/websocket/detail/prng.ipp index 2807ca96e9..2d4e7f2771 100644 --- a/boost/beast/websocket/detail/prng.ipp +++ b/boost/beast/websocket/detail/prng.ipp @@ -13,14 +13,10 @@ #include <boost/beast/websocket/detail/prng.hpp> #include <boost/beast/core/detail/chacha.hpp> #include <boost/beast/core/detail/pcg.hpp> -#include <boost/align/aligned_alloc.hpp> -#include <boost/throw_exception.hpp> #include <atomic> #include <cstdlib> #include <mutex> -#include <new> #include <random> -#include <stdexcept> namespace boost { namespace beast { @@ -59,264 +55,92 @@ prng_seed(std::seed_seq* ss) //------------------------------------------------------------------------------ -template<class T> -class prng_pool +inline +std::uint32_t +make_nonce() { - std::mutex m_; - T* head_ = nullptr; - -public: - static - prng_pool& - instance() - { - static prng_pool p; - return p; - } - - ~prng_pool() - { - for(auto p = head_; p;) - { - auto next = p->next; - p->~T(); - boost::alignment::aligned_free(p); - p = next; - } - } + static std::atomic<std::uint32_t> nonce{0}; + return ++nonce; +} - prng::ref - acquire() - { - { - std::lock_guard< - std::mutex> g(m_); - if(head_) - { - auto p = head_; - head_ = head_->next; - return prng::ref(*p); - } - } - auto p = boost::alignment::aligned_alloc( - 16, sizeof(T)); - if(! p) - BOOST_THROW_EXCEPTION(std::bad_alloc{}); - return prng::ref(*(::new(p) T())); - } +inline +beast::detail::pcg make_pcg() +{ + auto const pv = prng_seed(); + return beast::detail::pcg{ + ((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^ + ((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^ + ((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^ + ((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]), make_nonce()}; +} - void - release(T& t) - { - std::lock_guard< - std::mutex> g(m_); - t.next = head_; - head_ = &t; - } -}; +#ifdef BOOST_NO_CXX11_THREAD_LOCAL -prng::ref -make_prng_no_tls(bool secure) +inline +std::uint32_t +secure_generate() { - class fast_prng final : public prng + struct generator { - int refs_ = 0; - beast::detail::pcg r_; - - public: - fast_prng* next = nullptr; - - fast_prng() - : r_( - []{ - auto const pv = prng_seed(); - return - ((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^ - ((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^ - ((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^ - ((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]); - }(), - []{ - static std::atomic< - std::uint32_t> nonce{0}; - return ++nonce; - }()) - { - } - - protected: - prng& - acquire() noexcept override + std::uint32_t operator()() { - ++refs_; - return *this; + std::lock_guard<std::mutex> guard{mtx}; + return gen(); } - void - release() noexcept override - { - if(--refs_ == 0) - prng_pool<fast_prng>::instance().release(*this); - } - - value_type - operator()() noexcept override - { - return r_(); - } + beast::detail::chacha<20> gen; + std::mutex mtx; }; - - class secure_prng final : public prng - { - int refs_ = 0; - beast::detail::chacha<20> r_; - - public: - secure_prng* next = nullptr; - - secure_prng() - : r_(prng_seed(), [] - { - static std::atomic< - std::uint64_t> nonce{0}; - return ++nonce; - }()) - { - } - - protected: - prng& - acquire() noexcept override - { - ++refs_; - return *this; - } - - void - release() noexcept override - { - if(--refs_ == 0) - prng_pool<secure_prng>::instance().release(*this); - } - - value_type - operator()() noexcept override - { - return r_(); - } - }; - - if(secure) - return prng_pool<secure_prng>::instance().acquire(); - - return prng_pool<fast_prng>::instance().acquire(); + static generator gen{beast::detail::chacha<20>{prng_seed(), make_nonce()}}; + return gen(); } -//------------------------------------------------------------------------------ - -#ifndef BOOST_NO_CXX11_THREAD_LOCAL - -prng::ref -make_prng_tls(bool secure) +inline +std::uint32_t +fast_generate() { - class fast_prng final : public prng + struct generator { - beast::detail::pcg r_; - - public: - fast_prng() - : r_( - []{ - auto const pv = prng_seed(); - return - ((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^ - ((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^ - ((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^ - ((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]); - }(), - []{ - static std::atomic< - std::uint32_t> nonce{0}; - return ++nonce; - }()) - { - } - - protected: - prng& - acquire() noexcept override + std::uint32_t operator()() { - return *this; + std::lock_guard<std::mutex> guard{mtx}; + return gen(); } - void - release() noexcept override - { - } - - value_type - operator()() noexcept override - { - return r_(); - } + beast::detail::pcg gen; + std::mutex mtx; }; + static generator gen{make_pcg()}; + return gen(); +} - class secure_prng final : public prng - { - beast::detail::chacha<20> r_; - - public: - secure_prng() - : r_(prng_seed(), [] - { - static std::atomic< - std::uint64_t> nonce{0}; - return ++nonce; - }()) - { - } - - protected: - prng& - acquire() noexcept override - { - return *this; - } - - void - release() noexcept override - { - } - - value_type - operator()() noexcept override - { - return r_(); - } - }; +#else - if(secure) - { - thread_local secure_prng sp; - return prng::ref(sp); - } +inline +std::uint32_t +secure_generate() +{ + thread_local static beast::detail::chacha<20> gen{prng_seed(), make_nonce()}; + return gen(); +} - thread_local fast_prng fp; - return prng::ref(fp); +inline +std::uint32_t +fast_generate() +{ + thread_local static beast::detail::pcg gen{make_pcg()}; + return gen(); } #endif -//------------------------------------------------------------------------------ - -prng::ref +generator make_prng(bool secure) { -#ifdef BOOST_NO_CXX11_THREAD_LOCAL - return make_prng_no_tls(secure); -#else - return make_prng_tls(secure); -#endif + if (secure) + return &secure_generate; + else + return &fast_generate; } } // detail |