Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 09:00:18

0001 //
0002 // Copyright (c) 2025 Marcelo Zimbres Silva (mzimbres@gmail.com),
0003 // Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 
0009 #ifndef BOOST_REDIS_EXEC_FSM_IPP
0010 #define BOOST_REDIS_EXEC_FSM_IPP
0011 
0012 #include <boost/redis/detail/coroutine.hpp>
0013 #include <boost/redis/detail/exec_fsm.hpp>
0014 #include <boost/redis/request.hpp>
0015 
0016 #include <boost/asio/error.hpp>
0017 #include <boost/assert.hpp>
0018 
0019 namespace boost::redis::detail {
0020 
0021 inline bool is_partial_or_terminal_cancel(asio::cancellation_type_t type)
0022 {
0023    return !!(type & (asio::cancellation_type_t::partial | asio::cancellation_type_t::terminal));
0024 }
0025 
0026 inline bool is_total_cancel(asio::cancellation_type_t type)
0027 {
0028    return !!(type & asio::cancellation_type_t::total);
0029 }
0030 
0031 exec_action exec_fsm::resume(bool connection_is_open, asio::cancellation_type_t cancel_state)
0032 {
0033    switch (resume_point_) {
0034       BOOST_REDIS_CORO_INITIAL
0035 
0036       // Check whether the user wants to wait for the connection to
0037       // be established.
0038       if (elem_->get_request().get_config().cancel_if_not_connected && !connection_is_open) {
0039          BOOST_REDIS_YIELD(resume_point_, 1, exec_action_type::immediate)
0040          elem_.reset();  // Deallocate memory before finalizing
0041          return system::error_code(error::not_connected);
0042       }
0043 
0044       // No more immediate errors. Set up the supported cancellation types.
0045       // This is required to get partial and total cancellations.
0046       // This is a potentially allocating operation, so do it as late as we can.
0047       BOOST_REDIS_YIELD(resume_point_, 2, exec_action_type::setup_cancellation)
0048 
0049       // Add the request to the multiplexer
0050       mpx_->add(elem_);
0051 
0052       // Notify the writer task that there is work to do. If the task is not
0053       // listening (e.g. it's already writing or the connection is not healthy),
0054       // this is a no-op. Since this is sync, no cancellation can happen here.
0055       BOOST_REDIS_YIELD(resume_point_, 3, exec_action_type::notify_writer)
0056 
0057       while (true) {
0058          // Wait until we get notified. This will return once the request completes,
0059          // or upon any kind of cancellation
0060          BOOST_REDIS_YIELD(resume_point_, 4, exec_action_type::wait_for_response)
0061 
0062          // If the request has completed (with error or not), we're done
0063          if (elem_->is_done()) {
0064             exec_action act{elem_->get_error(), elem_->get_read_size()};
0065             elem_.reset();  // Deallocate memory before finalizing
0066             return act;
0067          }
0068 
0069          // Total cancellation can only be handled if the request hasn't been sent yet.
0070          // Partial and terminal cancellation can always be served
0071          if (
0072             (is_total_cancel(cancel_state) && elem_->is_waiting()) ||
0073             is_partial_or_terminal_cancel(cancel_state)) {
0074             mpx_->cancel(elem_);
0075             elem_.reset();  // Deallocate memory before finalizing
0076             return exec_action{asio::error::operation_aborted};
0077          }
0078       }
0079    }
0080 
0081    // We should never get here
0082    BOOST_ASSERT(false);
0083    return exec_action{system::error_code()};
0084 }
0085 
0086 }  // namespace boost::redis::detail
0087 
0088 #endif