Skip to content

Commit 4603b3e

Browse files
authored
Merge pull request ceph#60304 from cbodley/wip-async-completion-recycling
common/async: Completion uses asio::recycling_allocator by default Reviewed-by: Adam Emerson <[email protected]>
2 parents 0ee82db + 843daa9 commit 4603b3e

File tree

5 files changed

+42
-84
lines changed

5 files changed

+42
-84
lines changed

src/common/async/bind_handler.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
#define CEPH_ASYNC_BIND_HANDLER_H
1717

1818
#include <tuple>
19-
#include <boost/asio/associated_allocator.hpp>
20-
#include <boost/asio/associated_executor.hpp>
19+
#include <boost/asio/associator.hpp>
2120

2221
namespace ceph::async {
2322

@@ -52,25 +51,25 @@ struct CompletionHandler {
5251
void operator()() && {
5352
std::apply(std::move(handler), std::move(args));
5453
}
55-
56-
using allocator_type = boost::asio::associated_allocator_t<Handler>;
57-
allocator_type get_allocator() const noexcept {
58-
return boost::asio::get_associated_allocator(handler);
59-
}
6054
};
6155

6256
} // namespace ceph::async
6357

6458
namespace boost::asio {
6559

66-
// specialize boost::asio::associated_executor<> for CompletionHandler
67-
template <typename Handler, typename Tuple, typename Executor>
68-
struct associated_executor<ceph::async::CompletionHandler<Handler, Tuple>, Executor> {
69-
using type = boost::asio::associated_executor_t<Handler, Executor>;
70-
71-
static type get(const ceph::async::CompletionHandler<Handler, Tuple>& handler,
72-
const Executor& ex = Executor()) noexcept {
73-
return boost::asio::get_associated_executor(handler.handler, ex);
60+
// forward the handler's associated executor, allocator, cancellation slot, etc
61+
template <template <typename, typename> class Associator,
62+
typename Handler, typename Tuple, typename DefaultCandidate>
63+
struct associator<Associator,
64+
ceph::async::CompletionHandler<Handler, Tuple>, DefaultCandidate>
65+
: Associator<Handler, DefaultCandidate>
66+
{
67+
static auto get(const ceph::async::CompletionHandler<Handler, Tuple>& h) noexcept {
68+
return Associator<Handler, DefaultCandidate>::get(h.handler);
69+
}
70+
static auto get(const ceph::async::CompletionHandler<Handler, Tuple>& h,
71+
const DefaultCandidate& c) noexcept {
72+
return Associator<Handler, DefaultCandidate>::get(h.handler, c);
7473
}
7574
};
7675

src/common/async/bind_like.h

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/common/async/completion.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <boost/asio/defer.hpp>
2222
#include <boost/asio/dispatch.hpp>
2323
#include <boost/asio/executor_work_guard.hpp>
24+
#include <boost/asio/recycling_allocator.hpp>
2425
#include <boost/asio/post.hpp>
2526

2627
#include "bind_handler.h"
@@ -173,7 +174,8 @@ class CompletionImpl final : public Completion<void(Args...), T> {
173174
Handler handler;
174175

175176
// use Handler's associated allocator
176-
using Alloc2 = boost::asio::associated_allocator_t<Handler>;
177+
using DefaultAlloc = boost::asio::recycling_allocator<void>;
178+
using Alloc2 = boost::asio::associated_allocator_t<Handler, DefaultAlloc>;
177179
using Traits2 = std::allocator_traits<Alloc2>;
178180
using RebindAlloc2 = typename Traits2::template rebind_alloc<CompletionImpl>;
179181
using RebindTraits2 = std::allocator_traits<RebindAlloc2>;
@@ -196,16 +198,16 @@ class CompletionImpl final : public Completion<void(Args...), T> {
196198
void destroy_defer(std::tuple<Args...>&& args) override {
197199
auto w = std::move(work);
198200
auto ex2 = w.second.get_executor();
199-
RebindAlloc2 alloc2 = boost::asio::get_associated_allocator(handler);
201+
RebindAlloc2 alloc2 = boost::asio::get_associated_allocator(handler, DefaultAlloc{});
200202
auto f = bind_and_forward(ex2, std::move(handler), std::move(args));
201203
RebindTraits2::destroy(alloc2, this);
202204
RebindTraits2::deallocate(alloc2, this, 1);
203-
boost::asio::defer(boost::asio::bind_executor(ex2, std::move(f)));
205+
boost::asio::defer(std::move(f));
204206
}
205207
void destroy_dispatch(std::tuple<Args...>&& args) override {
206208
auto w = std::move(work);
207209
auto ex2 = w.second.get_executor();
208-
RebindAlloc2 alloc2 = boost::asio::get_associated_allocator(handler);
210+
RebindAlloc2 alloc2 = boost::asio::get_associated_allocator(handler, DefaultAlloc{});
209211
auto f = bind_and_forward(ex2, std::move(handler), std::move(args));
210212
RebindTraits2::destroy(alloc2, this);
211213
RebindTraits2::deallocate(alloc2, this, 1);
@@ -214,14 +216,14 @@ class CompletionImpl final : public Completion<void(Args...), T> {
214216
void destroy_post(std::tuple<Args...>&& args) override {
215217
auto w = std::move(work);
216218
auto ex2 = w.second.get_executor();
217-
RebindAlloc2 alloc2 = boost::asio::get_associated_allocator(handler);
219+
RebindAlloc2 alloc2 = boost::asio::get_associated_allocator(handler, DefaultAlloc{});
218220
auto f = bind_and_forward(ex2, std::move(handler), std::move(args));
219221
RebindTraits2::destroy(alloc2, this);
220222
RebindTraits2::deallocate(alloc2, this, 1);
221223
boost::asio::post(std::move(f));
222224
}
223225
void destroy() override {
224-
RebindAlloc2 alloc2 = boost::asio::get_associated_allocator(handler);
226+
RebindAlloc2 alloc2 = boost::asio::get_associated_allocator(handler, DefaultAlloc{});
225227
RebindTraits2::destroy(alloc2, this);
226228
RebindTraits2::deallocate(alloc2, this, 1);
227229
}
@@ -238,7 +240,7 @@ class CompletionImpl final : public Completion<void(Args...), T> {
238240
public:
239241
template <typename ...TArgs>
240242
static auto create(const Executor1& ex, Handler&& handler, TArgs&& ...args) {
241-
auto alloc2 = boost::asio::get_associated_allocator(handler);
243+
auto alloc2 = boost::asio::get_associated_allocator(handler, DefaultAlloc{});
242244
using Ptr = std::unique_ptr<CompletionImpl>;
243245
return Ptr{new (alloc2) CompletionImpl(ex, std::move(handler),
244246
std::forward<TArgs>(args)...)};

src/common/async/detail/shared_mutex.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <optional>
2020
#include <shared_mutex> // for std::shared_lock
2121

22+
#include <boost/asio/append.hpp>
2223
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
2324
#include <boost/intrusive_ptr.hpp>
2425
#include <boost/intrusive/list.hpp>
@@ -134,10 +135,8 @@ auto SharedMutexImpl::async_lock(Mutex& mtx, CompletionToken&& token)
134135
state = Exclusive;
135136

136137
// post a successful completion
137-
auto ex2 = boost::asio::get_associated_executor(handler, ex1);
138-
auto h = boost::asio::bind_executor(ex2, std::move(handler));
139-
boost::asio::post(bind_handler(std::move(h), ec,
140-
std::unique_lock{mtx, std::adopt_lock}));
138+
boost::asio::post(ex1, boost::asio::append(std::move(handler),
139+
ec, std::unique_lock{mtx, std::adopt_lock}));
141140
} else {
142141
// create a request and add it to the exclusive list
143142
using LockCompletion = typename Request::LockCompletion;
@@ -224,10 +223,8 @@ auto SharedMutexImpl::async_lock_shared(Mutex& mtx, CompletionToken&& token)
224223
if (exclusive_queue.empty() && state < MaxShared) {
225224
state++;
226225

227-
auto ex2 = boost::asio::get_associated_executor(handler, ex1);
228-
auto h = boost::asio::bind_executor(ex2, std::move(handler));
229-
boost::asio::post(bind_handler(std::move(h), ec,
230-
std::shared_lock{mtx, std::adopt_lock}));
226+
boost::asio::post(ex1, boost::asio::append(std::move(handler),
227+
ec, std::shared_lock{mtx, std::adopt_lock}));
231228
} else {
232229
using LockCompletion = typename Request::LockCompletion;
233230
auto request = LockCompletion::create(ex1, std::move(handler), mtx);

src/common/async/forward_handler.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
#ifndef CEPH_ASYNC_FORWARD_HANDLER_H
1616
#define CEPH_ASYNC_FORWARD_HANDLER_H
1717

18-
#include <boost/asio/associated_allocator.hpp>
19-
#include <boost/asio/associated_executor.hpp>
18+
#include <boost/asio/associator.hpp>
2019

2120
namespace ceph::async {
2221

@@ -47,25 +46,25 @@ struct ForwardingHandler {
4746
void operator()(Args&& ...args) {
4847
std::move(handler)(std::forward<Args>(args)...);
4948
}
50-
51-
using allocator_type = boost::asio::associated_allocator_t<Handler>;
52-
allocator_type get_allocator() const noexcept {
53-
return boost::asio::get_associated_allocator(handler);
54-
}
5549
};
5650

5751
} // namespace ceph::async
5852

5953
namespace boost::asio {
6054

61-
// specialize boost::asio::associated_executor<> for ForwardingHandler
62-
template <typename Handler, typename Executor>
63-
struct associated_executor<ceph::async::ForwardingHandler<Handler>, Executor> {
64-
using type = boost::asio::associated_executor_t<Handler, Executor>;
65-
66-
static type get(const ceph::async::ForwardingHandler<Handler>& handler,
67-
const Executor& ex = Executor()) noexcept {
68-
return boost::asio::get_associated_executor(handler.handler, ex);
55+
// forward the handler's associated executor, allocator, cancellation slot, etc
56+
template <template <typename, typename> class Associator,
57+
typename Handler, typename DefaultCandidate>
58+
struct associator<Associator,
59+
ceph::async::ForwardingHandler<Handler>, DefaultCandidate>
60+
: Associator<Handler, DefaultCandidate>
61+
{
62+
static auto get(const ceph::async::ForwardingHandler<Handler>& h) noexcept {
63+
return Associator<Handler, DefaultCandidate>::get(h.handler);
64+
}
65+
static auto get(const ceph::async::ForwardingHandler<Handler>& h,
66+
const DefaultCandidate& c) noexcept {
67+
return Associator<Handler, DefaultCandidate>::get(h.handler, c);
6968
}
7069
};
7170

0 commit comments

Comments
 (0)