使用Asio和自定义分配器创建一个异步的帖子。

huangapple go评论73阅读模式
英文:

Create an asynchronous post using Asio and custom allocator

问题

I am reading implementation of asio handlers using custom allocators.
manual

I am trying to implement my own custom allocator using pmr. But fails in compilation with the following error:

prog.cc: In instantiation of 'AsioHandler<Handler>::AsioHandler(Handler&&) [with Handler = main()::<lambda()>]':
prog.cc:77:35:   required from 'AsioHandler<typename std::remove_reference<_Tp>::type> make_custom_alloc_handler(Handler&&) [with Handler = main()::<lambda()>; typename std::remove_reference<_Tp>::type = main()::<lambda()>]'
prog.cc:84:55:   required from here
prog.cc:69:24: error: cannot convert '<brace-enclosed initializer list>' to 'memory_resource*' in initialization    69 |    
memory_resource  * alloc_{&pool_};
      |                        ^~~~~~
In file included from /opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio.hpp:52,
                 from prog.cc:13: /opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio/bind_executor.hpp:
In instantiation of 'boost::asio::detail::executor_binder_base<T, Executor, false>::executor_binder_base(E&&, U&&) [with E = const boost::asio::io_context::basic_executor_type<std::allocator<void>, 0>&; U = AsioHandler<main()::<lambda()>>; T = AsioHandler<main()::<lambda()>>; Executor = boost::asio::io_context::basic_executor_type<std::allocator<void>, 0>]':
/opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio/bind_executor.hpp:295:46: required from 'boost::asio::executor_binder<T, Executor>::executor_binder(boost::asio::executor_arg_t, const executor_type&, U&&) [with U = AsioHandler<main()::<lambda()>>; T = AsioHandler<main()::<lambda()>>; Executor = boost::asio::io_context::basic_executor_type<std::allocator<void>, 0>; executor_type = boost::asio::io_context::basic_executor_type<std::allocator<void>, 0>]'
/opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio/bind_executor.hpp:508:10: required from 'boost::asio::executor_binder<typename std::decay<_Tp2>::type, typename ExecutionContext::executor_type> boost::asio::bind_executor(ExecutionContext&, T&&, typename constraint<std::is_convertible<ExecutionContext&, execution_context&>>::value>::type) [with ExecutionContext = io_context; T = AsioHandler<main()::<lambda()>>; typename ExecutionContext::executor_type = io_context::basic_executor_type<std::allocator<void>, 0>; typename std::decay<_Tp2>::type = std::decay<AsioHandler<main()::<lambda()>>>::type; typename constraint<std::is_convertible<ExecutionContext&, execution_context&>>::value>::type = int]'
prog.cc:86:49:   required from here
/opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio/bind_executor.hpp:181:7: error: call of overloaded 'AsioHandler(AsioHandler<main()::<lambda()>>)' is ambiguous

How to fix this?

英文:

I am reading implementation of asio handlers using custom allocators.
manual

I am trying to implement my own custom allocator using pmr. But fails in compilation with the following error

prog.cc: In instantiation of
&#39;AsioHandler&lt;Handler&gt;::AsioHandler(Handler&amp;&amp;) [with Handler = main()::&lt;lambda()&gt;]&#39;:
prog.cc:77:35:   required from &#39;AsioHandler&lt;typename std::remove_reference&lt;_Tp&gt;::type&gt; make_custom_alloc_handler(Handler&amp;&amp;) [with Handler = main()::&lt;lambda()&gt;; typename std::remove_reference&lt;_Tp&gt;::type =
main()::&lt;lambda()&gt;]&#39;
prog.cc:84:55:   required from here
prog.cc:69:24: error: cannot convert &#39;&lt;brace-enclosed initializer list&gt;&#39; to &#39;memory_resource*&#39; in initialization    69 |    
memory_resource  * alloc_{&amp;pool_};
|                        ^~~~~~
In file included from /opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio.hpp:52,
from prog.cc:13: /opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio/bind_executor.hpp:
In instantiation of &#39;boost::asio::detail::executor_binder_base&lt;T, Executor, false&gt;::executor_binder_base(E&amp;&amp;, U&amp;&amp;) [with E = const boost::asio::io_context::basic_executor_type&lt;std::allocator&lt;void&gt;, 0&gt;&amp;; U = AsioHandler&lt;main()::&lt;lambda()&gt; &gt;; T = AsioHandler&lt;main()::&lt;lambda()&gt; &gt;; Executor = boost::asio::io_context::basic_executor_type&lt;std::allocator&lt;void&gt;, 0&gt;]&#39;:
/opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio/bind_executor.hpp:295:46: required from &#39;boost::asio::executor_binder&lt;T, Executor&gt;::executor_binder(boost::asio::executor_arg_t, const executor_type&amp;, U&amp;&amp;) [with U = AsioHandler&lt;main()::&lt;lambda()&gt; &gt;; T = AsioHandler&lt;main()::&lt;lambda()&gt; &gt;; Executor = boost::asio::io_context::basic_executor_type&lt;std::allocator&lt;void&gt;, 0&gt;; executor_type = boost::asio::io_context::basic_executor_type&lt;std::allocator&lt;void&gt;, 0&gt;]&#39;
/opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio/bind_executor.hpp:508:10: required from &#39;boost::asio::executor_binder&lt;typename std::decay&lt;_Tp2&gt;::type, typename ExecutionContext::executor_type&gt; boost::asio::bind_executor(ExecutionContext&amp;, T&amp;&amp;, typename constraint&lt;std::is_convertible&lt;ExecutionContext&amp;, execution_context&amp;&gt;::value&gt;::type) [with ExecutionContext = io_context; T = AsioHandler&lt;main()::&lt;lambda()&gt; &gt;; typename ExecutionContext::executor_type = io_context::basic_executor_type&lt;std::allocator&lt;void&gt;, 0&gt;; typename std::decay&lt;_Tp2&gt;::type = std::decay&lt;AsioHandler&lt;main()::&lt;lambda()&gt; &gt; ::type; typename constraint&lt;std::is_convertible&lt;ExecutionContext&amp;, execution_context&amp;&gt;::value&gt;::type = int]&#39;
prog.cc:86:49:   required from here
/opt/wandbox/boost-1.81.0-gcc-12.2.0/include/boost/asio/bind_executor.hpp:181:7: error: call of overloaded &#39;AsioHandler(AsioHandler&lt;main()::&lt;lambda()&gt;)&#39; is ambiguous
#include &lt;boost/container/pmr/monotonic_buffer_resource.hpp&gt;
#include  &lt;boost/container/pmr/global_resource.hpp&gt;
#include &lt;cstdlib&gt;
#include &lt;iostream&gt;
#include &lt;thread&gt;
#include &lt;boost/aligned_storage.hpp&gt;
#include &lt;boost/array.hpp&gt;
#include &lt;boost/bind.hpp&gt;
#include &lt;boost/enable_shared_from_this.hpp&gt;
#include &lt;boost/noncopyable.hpp&gt;
#include &lt;boost/shared_ptr.hpp&gt;
#include &lt;boost/asio.hpp&gt;
#include &lt;boost/asio/post.hpp&gt;
namespace bc = boost::container;
class memory_resource: public bc::pmr::memory_resource
{
public:
explicit memory_resource(bc::pmr::memory_resource* up = bc::pmr::get_default_resource())
:upstream_(up){}
void* do_allocate(size_t bytes, size_t alignment) override {
void* ret = upstream_-&gt;allocate(bytes, alignment);
return ret;
}
void do_deallocate(void* ptr, size_t bytes, size_t alignment) override {
upstream_-&gt;deallocate(ptr, bytes, alignment);
}
bool do_is_equal(const bc::pmr::memory_resource&amp; other) const noexcept override {
return this == &amp;other;
}
private:
bc::pmr::memory_resource* upstream_;
};
//template&lt;typename Handler,size_t S = 2048&gt;
constexpr std::size_t S = 2048 ;
template&lt;typename Handler&gt;
class AsioHandler: public Handler
{
public:
using Handler::operator();
AsioHandler(Handler &amp;&amp; h)
:h_(std::forward&lt;Handler&gt;(h))
{
}
memory_resource  * get_allocator() const noexcept
{
return alloc_;
}
friend void* asio_handler_allocate(std::size_t size
,AsioHandler&lt;Handler&gt;* this_handler)
{
return this_handler-&gt;alloc_-&gt;do_allocate(size,S);
}
friend void asio_handler_deallocate(void* pointer, std::size_t size
,AsioHandler&lt;Handler&gt;* this_handler)
{
this_handler-&gt;alloc_-&gt;do_deallocate(pointer,size,S);
}
private:
Handler h_;
typename std::aligned_storage&lt;S&gt;::type storage_;
boost::container::pmr::monotonic_buffer_resource pool_{&amp;storage_,S};
memory_resource  * alloc_{&amp;pool_};
};
// Helper function to wrap a handler object to add custom allocation.
template &lt;typename Handler&gt;
AsioHandler&lt;typename std::remove_reference&lt;Handler&gt;::type&gt; 
make_custom_alloc_handler(Handler &amp;&amp; h)
{
return {std::forward&lt;Handler&gt;(h)};
}
int main()
{
boost::asio::io_context ctx;
auto func = [](){};
auto  h = make_custom_alloc_handler&lt;decltype(func)&gt;(std::move(func));
boost::asio::post(boost::asio::bind_executor(ctx, std::move(h)));
std::thread t {[&amp;ctx]()
{
ctx.run();
}
};
t.join();
}

How to fix this?

答案1

得分: 2

这段代码涉及到C++的技术细节和库,包括Boost.Asio、Boost.Container等。这是一份对代码的批注,指出了其中一些问题和改进的建议。如果你需要进一步的帮助或有特定问题,请随时提出。

英文:

That's... a lot of code. It has a ton of unused headers, unnecessary threads, a duplicated Handler h_ member which is already a base class (!), the invalid forward&lt;&gt; on a non-deduced rvalue reference, missing allocator_type typedef, questionable do_is_equal implementation, using remove_reference_t instead of decay_t, etc.

> It seems like you hardcode the alignment parameter on every do_allocate call to be equal to the S of the the pool... Is this intended?

Next up, your memory_resource subclass shadows bc::pmr::memory_resource making your code hard to grok. E.g., which did you mean to use for AsioHandler::alloc_? I'd assume your own (let's call it my_memory_resource for now), but the initializer isn't compatible at all. Did you mean my_memory_resource instead of my_memory_resource*?

Regardless of everything, pool_ being of type bc::pmc::monotonic_buffer_resource makes AsioHandler non-copyable by definition.

All this combined really makes me scratch my head how you even got the compiler message you posted in the first place.

I can make your code compile by fixing the non-copyability (making AsioHandler move-only), but I will not vouch for this code to be useful:

Live On Coliru

#include &lt;boost/aligned_storage.hpp&gt;
#include &lt;boost/asio.hpp&gt;
#include &lt;boost/container/pmr/global_resource.hpp&gt;
#include &lt;boost/container/pmr/monotonic_buffer_resource.hpp&gt;
#include &lt;cstdlib&gt;
#include &lt;iostream&gt;
// #include &lt;boost/array.hpp&gt;
// #include &lt;boost/asio/post.hpp&gt;
// #include &lt;boost/bind/bind.hpp&gt;
// #include &lt;boost/enable_shared_from_this.hpp&gt;
// #include &lt;boost/noncopyable.hpp&gt;
// #include &lt;boost/shared_ptr.hpp&gt;
namespace bc = boost::container;
class my_memory_resource : public bc::pmr::memory_resource
{
public:
explicit my_memory_resource(
bc::pmr::memory_resource* up = bc::pmr::get_default_resource())
: upstream_(up)
{
}
void* do_allocate(size_t bytes, size_t alignment) override
{
void* ret = upstream_-&gt;allocate(bytes, alignment);
return ret;
}
void do_deallocate(
void* ptr, size_t bytes, size_t alignment) override
{
upstream_-&gt;deallocate(ptr, bytes, alignment);
}
bool do_is_equal(
bc::pmr::memory_resource const&amp; other) const noexcept override
{
return this ==
&amp;other; // SEHE FIXME https://en.cppreference.com/w/cpp/memory/memory_resource/do_is_equal
}
private:
bc::pmr::memory_resource* upstream_;
};
// template&lt;typename Handler,size_t S = 2048&gt;
constexpr std::size_t S = 2048;
template &lt;typename Handler&gt; struct AsioHandler : Handler {
using Handler::operator();
explicit AsioHandler(Handler h) : Handler(std::move(h)) {}
my_memory_resource* get_allocator() noexcept { return alloc_.get(); }
friend void* asio_handler_allocate(std::size_t size, AsioHandler&lt;Handler&gt;* h) {
return h-&gt;alloc_-&gt;do_allocate(size, S);
}
friend void asio_handler_deallocate(void* pointer, std::size_t size, AsioHandler&lt;Handler&gt;* h) {
h-&gt;alloc_-&gt;do_deallocate(pointer, size, S);
}
private:
// Handler h_;
typename std::aligned_storage&lt;S&gt;::type storage_;
std::unique_ptr&lt;bc::pmr::monotonic_buffer_resource&gt; pool_ =
std::make_unique&lt;bc::pmr::monotonic_buffer_resource&gt;(&amp;storage_, S);
std::unique_ptr&lt;my_memory_resource&gt; alloc_ = std::make_unique&lt;my_memory_resource&gt;(pool_.get());
};
// Helper function to wrap a handler object to add custom allocation.
template &lt;typename Handler&gt; AsioHandler&lt;std::decay_t&lt;Handler&gt;&gt; make_custom_alloc_handler(Handler&amp;&amp; h) {
return AsioHandler&lt;std::decay_t&lt;Handler&gt;&gt;{std::forward&lt;Handler&gt;(h)};
}
int main()
{
boost::asio::io_context ctx;
auto func = []() { std::cout &lt;&lt; &quot;SEHE WAS HERE&quot; &lt;&lt; std::endl; };
auto h    = make_custom_alloc_handler&lt;decltype(func)&gt;(std::move(func));
// boost::asio::post(ctx, std::move(h));
boost::asio::post(boost::asio::bind_executor(ctx, std::move(h)));
ctx.run();
}

Prints

SEHE WAS HERE

huangapple
  • 本文由 发表于 2023年5月13日 17:05:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76241917.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定