3 #include <ozo/type_traits.h>
5 #include <ozo/deadline.h>
6 #include <ozo/connection.h>
23 #ifdef OZO_DOCUMENTATION
117 template <
typename T>
129 template <
typename T>
134 namespace ozo::failover {
136 namespace hana = boost::hana;
148 typename TimeConstraint,
151 static_assert(ozo::TimeConstraint<TimeConstraint>,
"TimeConstraint should models ozo::TimeConstraint");
152 static_assert(ozo::ConnectionProvider<ConnectionProvider>,
"ConnectionProvider should models ozo::ConnectionProvider");
156 hana::tuple<std::decay_t<Args>...>
args;
168 args(std::forward<Args>(
args)...) {}
171 template <
typename FailoverStrategy,
typename Operation>
172 struct get_first_try_impl {
173 template <
typename Allocator,
typename ...Args>
174 static auto apply(
const Operation& op,
const FailoverStrategy& s,
const Allocator& alloc, Args&& ...args) {
175 return s.get_first_try(op, alloc, std::forward<Args>(args)...);
212 template <
typename FailoverStrategy,
typename Operation,
typename Allocator,
typename ...Args>
214 return get_first_try_impl<FailoverStrategy, Operation>::apply(op, strategy, alloc, std::forward<Args>(args)...);
217 template <
typename Try>
218 struct get_try_context_impl {
219 static decltype(
auto) apply(const Try& a_try) {
220 return a_try.get_context();
251 template <
typename FailoverTry>
253 auto res = detail::apply<get_try_context_impl>(
ozo::unwrap(a_try));
254 static_assert(HanaSequence<decltype(res)>,
255 "get_try_context_impl::apply() should provide HanaSequence");
259 template <
typename Try>
260 struct get_next_try_impl {
261 template <
typename Conn>
262 static auto apply(Try& a_try,
error_code ec, Conn&& conn) {
263 return a_try.get_next_try(ec, conn);
305 template <
typename Try,
typename Connection>
307 return detail::apply<get_next_try_impl>(
ozo::unwrap(a_try), ec, conn);
310 template <
typename Try>
311 struct initiate_next_try_impl {
312 template <
typename Connection,
typename Initiator>
315 init(std::move(next));
360 template <
typename Try,
typename Connection,
typename Initiator>
362 return detail::apply<initiate_next_try_impl>(
ozo::unwrap(a_try), ec, conn, std::forward<Initiator>(init));
367 template <
template<
typename...>
typename Template,
typename Allocator,
typename ...Ts>
368 static auto allocate_shared(
const Allocator& alloc, Ts&& ...vs) {
369 using type = decltype(Template{std::forward<Ts>(vs)...});
370 return std::allocate_shared<type>(alloc, std::forward<Ts>(vs)...);
373 template <
typename Try,
typename Operation,
typename Handler>
374 inline void initiate_operation(
const Operation&, Try&&,
Handler&&);
376 template <
typename Operation,
typename Try,
typename Handler>
377 struct continuation {
382 continuation(
const Operation& op, Try a_try,
Handler handler)
383 : op_(op), try_(std::move(a_try)), handler_(std::move(handler)) {}
385 template <
typename Connection>
387 static_assert(ozo::Connection<Connection>,
"conn should model Connection concept");
389 bool initiated =
false;
392 initiate_operation(op_, std::move(next_try), std::move(handler_));
400 handler_(std::move(ec), std::forward<Connection>(conn));
403 using executor_type = decltype(asio::get_associated_executor(handler_));
406 return asio::get_associated_executor(handler_);
409 using allocator_type = decltype(asio::get_associated_allocator(handler_));
411 allocator_type get_allocator()
const {
412 return asio::get_associated_allocator(handler_);
416 template <
typename Try,
typename Operation,
typename Handler>
417 inline void initiate_operation(
const Operation& op, Try&& a_try,
Handler&& handler) {
420 continuation{op, std::forward<Try>(a_try), std::forward<Handler>(handler)},
421 std::forward<decltype(args)>(args)...
426 template <
typename FailoverStrategy,
typename Operation>
427 struct operation_initiator {
431 constexpr operation_initiator(
FailoverStrategy strategy,
const Operation& op)
432 : strategy_(std::move(strategy)), op_(op) {}
434 template <
typename Handler,
typename ...Args>
435 void operator() (
Handler&& handler, Args&& ...args)
const {
436 auto first_try =
get_first_try(op_, strategy_, asio::get_associated_allocator(handler), std::forward<Args>(args)...);
437 initiate_operation(op_, std::move(first_try), std::forward<Handler>(handler));
443 struct construct_initiator_impl {
444 template <
typename FailoverStrategy,
typename Op>
446 return detail::operation_initiator(std::forward<FailoverStrategy>(strategy), op);