mirror of
https://github.com/boostorg/beast.git
synced 2025-08-03 23:04:35 +02:00
Remove session_alloc (API Change)
* session_alloc is removed, as it does not improve performance as intended. Actions Required: * Don't use session_alloc
This commit is contained in:
@@ -3,6 +3,11 @@ Version 225:
|
|||||||
* Tidy up an unused function
|
* Tidy up an unused function
|
||||||
* Fix wsload jamfile
|
* Fix wsload jamfile
|
||||||
* Examples use flat_buffer
|
* Examples use flat_buffer
|
||||||
|
* Remove session_alloc (API Change)
|
||||||
|
|
||||||
|
Actions Required:
|
||||||
|
|
||||||
|
* Don't use session_alloc
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -1,455 +0,0 @@
|
|||||||
//
|
|
||||||
// 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_EXAMPLE_COMMON_SESSION_ALLOC_HPP
|
|
||||||
#define BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP
|
|
||||||
|
|
||||||
#include <boost/asio/associated_allocator.hpp>
|
|
||||||
#include <boost/asio/associated_executor.hpp>
|
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/core/ignore_unused.hpp>
|
|
||||||
#include <boost/intrusive/list.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <mutex>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<class Context>
|
|
||||||
class session_alloc_base
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
class pool_t
|
|
||||||
{
|
|
||||||
using hook_type =
|
|
||||||
boost::intrusive::list_base_hook<
|
|
||||||
boost::intrusive::link_mode<
|
|
||||||
boost::intrusive::normal_link>>;
|
|
||||||
|
|
||||||
class element : public hook_type
|
|
||||||
{
|
|
||||||
std::size_t size_;
|
|
||||||
std::size_t used_;
|
|
||||||
// add padding here
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit
|
|
||||||
element(std::size_t size, std::size_t used)
|
|
||||||
: size_(size)
|
|
||||||
, used_(used)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
size() const
|
|
||||||
{
|
|
||||||
return size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
used() const
|
|
||||||
{
|
|
||||||
return used_;
|
|
||||||
}
|
|
||||||
|
|
||||||
char*
|
|
||||||
end() const
|
|
||||||
{
|
|
||||||
return data() + size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
char*
|
|
||||||
data() const
|
|
||||||
{
|
|
||||||
return const_cast<char*>(
|
|
||||||
reinterpret_cast<
|
|
||||||
char const *>(this + 1));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using list_type = typename
|
|
||||||
boost::intrusive::make_list<element,
|
|
||||||
boost::intrusive::constant_time_size<
|
|
||||||
true>>::type;
|
|
||||||
|
|
||||||
std::mutex m_;
|
|
||||||
std::size_t refs_ = 1; // shared count
|
|
||||||
std::size_t high_ = 0; // highest used
|
|
||||||
std::size_t size_ = 0; // size of buf_
|
|
||||||
char* buf_ = nullptr; // a large block
|
|
||||||
list_type list_; // list of allocations
|
|
||||||
|
|
||||||
pool_t() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static
|
|
||||||
pool_t&
|
|
||||||
construct();
|
|
||||||
|
|
||||||
~pool_t();
|
|
||||||
|
|
||||||
pool_t&
|
|
||||||
addref();
|
|
||||||
|
|
||||||
void
|
|
||||||
release();
|
|
||||||
|
|
||||||
void*
|
|
||||||
alloc(std::size_t n);
|
|
||||||
|
|
||||||
void
|
|
||||||
dealloc(void* pv, std::size_t n);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Context>
|
|
||||||
auto
|
|
||||||
session_alloc_base<Context>::
|
|
||||||
pool_t::
|
|
||||||
construct() ->
|
|
||||||
pool_t&
|
|
||||||
{
|
|
||||||
return *(new pool_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Context>
|
|
||||||
session_alloc_base<Context>::
|
|
||||||
pool_t::
|
|
||||||
~pool_t()
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(list_.size() == 0);
|
|
||||||
if(buf_)
|
|
||||||
delete[] buf_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Context>
|
|
||||||
auto
|
|
||||||
session_alloc_base<Context>::
|
|
||||||
pool_t::
|
|
||||||
addref() ->
|
|
||||||
pool_t&
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
++refs_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Context>
|
|
||||||
void
|
|
||||||
session_alloc_base<Context>::
|
|
||||||
pool_t::
|
|
||||||
release()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
if(--refs_)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Context>
|
|
||||||
void*
|
|
||||||
session_alloc_base<Context>::
|
|
||||||
pool_t::
|
|
||||||
alloc(std::size_t n)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
if(list_.empty() && size_ < high_)
|
|
||||||
{
|
|
||||||
if(buf_)
|
|
||||||
delete[] buf_;
|
|
||||||
buf_ = new char[high_];
|
|
||||||
size_ = high_;
|
|
||||||
}
|
|
||||||
if(buf_)
|
|
||||||
{
|
|
||||||
char* end;
|
|
||||||
std::size_t used;
|
|
||||||
if(list_.empty())
|
|
||||||
{
|
|
||||||
end = buf_;
|
|
||||||
used = sizeof(element) + n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = list_.back().end();
|
|
||||||
used = list_.back().used() +
|
|
||||||
sizeof(element) + n;
|
|
||||||
}
|
|
||||||
if(end >= buf_ && end +
|
|
||||||
sizeof(element) + n <= buf_ + size_)
|
|
||||||
{
|
|
||||||
auto& e = *::new(end) element{n, used};
|
|
||||||
list_.push_back(e);
|
|
||||||
high_ = (std::max)(high_, used);
|
|
||||||
return e.data();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::size_t const used =
|
|
||||||
sizeof(element) + n + (
|
|
||||||
buf_ && ! list_.empty() ?
|
|
||||||
list_.back().used() : 0);
|
|
||||||
auto& e = *new(new char[sizeof(element) + n]) element{n, used};
|
|
||||||
list_.push_back(e);
|
|
||||||
high_ = (std::max)(high_, used);
|
|
||||||
return e.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Context>
|
|
||||||
void
|
|
||||||
session_alloc_base<Context>::
|
|
||||||
pool_t::
|
|
||||||
dealloc(void* pv, std::size_t n)
|
|
||||||
{
|
|
||||||
boost::ignore_unused(n);
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
auto& e = *(reinterpret_cast<element*>(pv) - 1);
|
|
||||||
BOOST_ASSERT(e.size() == n);
|
|
||||||
if( (e.end() > buf_ + size_) ||
|
|
||||||
reinterpret_cast<char*>(&e) < buf_)
|
|
||||||
{
|
|
||||||
list_.erase(list_.iterator_to(e));
|
|
||||||
e.~element();
|
|
||||||
delete[] reinterpret_cast<char*>(&e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
list_.erase(list_.iterator_to(e));
|
|
||||||
e.~element();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template<class Handler>
|
|
||||||
class session_alloc_wrapper;
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class session_alloc
|
|
||||||
: private detail::session_alloc_base<void>
|
|
||||||
{
|
|
||||||
template<class U>
|
|
||||||
friend class session_alloc;
|
|
||||||
|
|
||||||
using pool_t = typename
|
|
||||||
detail::session_alloc_base<void>::pool_t;
|
|
||||||
|
|
||||||
pool_t& pool_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
using is_always_equal = std::false_type;
|
|
||||||
using pointer = T*;
|
|
||||||
using reference = T&;
|
|
||||||
using const_pointer = T const*;
|
|
||||||
using const_reference = T const&;
|
|
||||||
using size_type = std::size_t;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
|
|
||||||
template<class U>
|
|
||||||
struct rebind
|
|
||||||
{
|
|
||||||
using other = session_alloc<U>;
|
|
||||||
};
|
|
||||||
|
|
||||||
session_alloc& operator=(session_alloc const&) = delete;
|
|
||||||
|
|
||||||
~session_alloc()
|
|
||||||
{
|
|
||||||
pool_.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
session_alloc()
|
|
||||||
: pool_(pool_t::construct())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
session_alloc(session_alloc const& other) noexcept
|
|
||||||
: pool_(other.pool_.addref())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class U>
|
|
||||||
session_alloc(session_alloc<U> const& other) noexcept
|
|
||||||
: pool_(other.pool_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Handler>
|
|
||||||
detail::session_alloc_wrapper<typename std::decay<Handler>::type>
|
|
||||||
wrap(Handler&& handler);
|
|
||||||
|
|
||||||
value_type*
|
|
||||||
allocate(size_type n)
|
|
||||||
{
|
|
||||||
return static_cast<value_type*>(
|
|
||||||
this->alloc(n * sizeof(T)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
deallocate(value_type* p, size_type n)
|
|
||||||
{
|
|
||||||
this->dealloc(p, n * sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
|
|
||||||
template<class U, class... Args>
|
|
||||||
void
|
|
||||||
construct(U* ptr, Args&&... args)
|
|
||||||
{
|
|
||||||
::new(static_cast<void*>(ptr)) U(
|
|
||||||
std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class U>
|
|
||||||
void
|
|
||||||
destroy(U* ptr)
|
|
||||||
{
|
|
||||||
ptr->~U();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<class U>
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
operator==(
|
|
||||||
session_alloc const& lhs,
|
|
||||||
session_alloc<U> const& rhs)
|
|
||||||
{
|
|
||||||
return &lhs.pool_ == &rhs.pool_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class U>
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
operator!=(
|
|
||||||
session_alloc const& lhs,
|
|
||||||
session_alloc<U> const& rhs)
|
|
||||||
{
|
|
||||||
return ! (lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void*
|
|
||||||
alloc(std::size_t n)
|
|
||||||
{
|
|
||||||
return pool_.alloc(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dealloc(void* p, std::size_t n)
|
|
||||||
{
|
|
||||||
pool_.dealloc(p, n);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<class Handler>
|
|
||||||
class session_alloc_wrapper
|
|
||||||
{
|
|
||||||
// Can't friend partial specializations,
|
|
||||||
// so we just friend the whole thing.
|
|
||||||
template<class U, class Executor>
|
|
||||||
friend struct boost::asio::associated_executor;
|
|
||||||
|
|
||||||
Handler h_;
|
|
||||||
session_alloc<char> alloc_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
session_alloc_wrapper(session_alloc_wrapper&&) = default;
|
|
||||||
session_alloc_wrapper(session_alloc_wrapper const&) = default;
|
|
||||||
|
|
||||||
template<class DeducedHandler>
|
|
||||||
session_alloc_wrapper(
|
|
||||||
DeducedHandler&& h,
|
|
||||||
session_alloc<char> const& alloc)
|
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
|
||||||
, alloc_(alloc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
using allocator_type = session_alloc<char>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept;
|
|
||||||
|
|
||||||
template<class... Args>
|
|
||||||
void
|
|
||||||
operator()(Args&&... args)
|
|
||||||
{
|
|
||||||
h_(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
asio_handler_is_continuation(session_alloc_wrapper* w)
|
|
||||||
{
|
|
||||||
using boost::asio::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(std::addressof(w->h_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Handler>
|
|
||||||
auto
|
|
||||||
session_alloc_wrapper<Handler>::
|
|
||||||
get_allocator() const noexcept ->
|
|
||||||
allocator_type
|
|
||||||
{
|
|
||||||
return alloc_;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
template<class Handler>
|
|
||||||
auto
|
|
||||||
session_alloc<T>::
|
|
||||||
wrap(Handler&& handler) ->
|
|
||||||
detail::session_alloc_wrapper<typename std::decay<Handler>::type>
|
|
||||||
{
|
|
||||||
return detail::session_alloc_wrapper<
|
|
||||||
typename std::decay<Handler>::type>(
|
|
||||||
std::forward<Handler>(handler), *this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace asio {
|
|
||||||
template<class Handler, class Executor>
|
|
||||||
struct associated_executor<
|
|
||||||
::detail::session_alloc_wrapper<Handler>, Executor>
|
|
||||||
{
|
|
||||||
using type = typename
|
|
||||||
associated_executor<Handler, Executor>::type;
|
|
||||||
|
|
||||||
static
|
|
||||||
type
|
|
||||||
get(::detail::session_alloc_wrapper<Handler> const& h,
|
|
||||||
Executor const& ex = Executor()) noexcept
|
|
||||||
{
|
|
||||||
return associated_executor<
|
|
||||||
Handler, Executor>::get(h.h_, ex);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // asio
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#endif
|
|
@@ -15,8 +15,6 @@
|
|||||||
//
|
//
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <example/common/session_alloc.hpp>
|
|
||||||
|
|
||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
#include <boost/beast/_experimental/unit_test/dstream.hpp>
|
#include <boost/beast/_experimental/unit_test/dstream.hpp>
|
||||||
@@ -119,7 +117,6 @@ class connection
|
|||||||
std::mt19937_64 rng_;
|
std::mt19937_64 rng_;
|
||||||
std::size_t count_ = 0;
|
std::size_t count_ = 0;
|
||||||
std::size_t bytes_ = 0;
|
std::size_t bytes_ = 0;
|
||||||
session_alloc<char> alloc_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
connection(
|
connection(
|
||||||
@@ -153,9 +150,9 @@ public:
|
|||||||
run()
|
run()
|
||||||
{
|
{
|
||||||
ws_.next_layer().async_connect(ep_,
|
ws_.next_layer().async_connect(ep_,
|
||||||
alloc_.wrap(beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&connection::on_connect,
|
&connection::on_connect,
|
||||||
this->shared_from_this())));
|
this->shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -168,9 +165,9 @@ private:
|
|||||||
ws_.async_handshake(
|
ws_.async_handshake(
|
||||||
ep_.address().to_string() + ":" + std::to_string(ep_.port()),
|
ep_.address().to_string() + ":" + std::to_string(ep_.port()),
|
||||||
"/",
|
"/",
|
||||||
alloc_.wrap(beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&connection::on_handshake,
|
&connection::on_handshake,
|
||||||
this->shared_from_this())));
|
this->shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -189,9 +186,9 @@ private:
|
|||||||
double(4) / beast::buffer_size(tb_)};
|
double(4) / beast::buffer_size(tb_)};
|
||||||
ws_.async_write_some(true,
|
ws_.async_write_some(true,
|
||||||
beast::buffers_prefix(dist(rng_), tb_),
|
beast::buffers_prefix(dist(rng_), tb_),
|
||||||
alloc_.wrap(beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&connection::on_write,
|
&connection::on_write,
|
||||||
this->shared_from_this())));
|
this->shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -204,18 +201,18 @@ private:
|
|||||||
return do_read();
|
return do_read();
|
||||||
|
|
||||||
ws_.async_close({},
|
ws_.async_close({},
|
||||||
alloc_.wrap(beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&connection::on_close,
|
&connection::on_close,
|
||||||
this->shared_from_this())));
|
this->shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
do_read()
|
do_read()
|
||||||
{
|
{
|
||||||
ws_.async_read(buffer_,
|
ws_.async_read(buffer_,
|
||||||
alloc_.wrap(beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&connection::on_read,
|
&connection::on_read,
|
||||||
this->shared_from_this())));
|
this->shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -20,7 +20,6 @@ add_executable (tests-example-common
|
|||||||
Jamfile
|
Jamfile
|
||||||
root_certificates.cpp
|
root_certificates.cpp
|
||||||
server_certificate.cpp
|
server_certificate.cpp
|
||||||
session_alloc.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(TARGET tests-example-common PROPERTY FOLDER "tests")
|
set_property(TARGET tests-example-common PROPERTY FOLDER "tests")
|
@@ -10,7 +10,6 @@
|
|||||||
local SOURCES =
|
local SOURCES =
|
||||||
root_certificates.cpp
|
root_certificates.cpp
|
||||||
server_certificate.cpp
|
server_certificate.cpp
|
||||||
session_alloc.cpp
|
|
||||||
;
|
;
|
||||||
|
|
||||||
local RUN_TESTS ;
|
local RUN_TESTS ;
|
||||||
|
@@ -1,12 +0,0 @@
|
|||||||
//
|
|
||||||
// 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
|
|
||||||
//
|
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
|
||||||
#include "example/common/session_alloc.hpp"
|
|
||||||
|
|
Reference in New Issue
Block a user