summaryrefslogtreecommitdiff
path: root/boost/beast/websocket/detail/prng.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/websocket/detail/prng.ipp')
-rw-r--r--boost/beast/websocket/detail/prng.ipp294
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