File indexing completed on 2025-04-19 08:33:52
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_IMPL_INTERNAL_SANSIO_TOP_LEVEL_ALGO_HPP
0009 #define BOOST_MYSQL_IMPL_INTERNAL_SANSIO_TOP_LEVEL_ALGO_HPP
0010
0011 #include <boost/mysql/client_errc.hpp>
0012 #include <boost/mysql/error_code.hpp>
0013
0014 #include <boost/mysql/detail/next_action.hpp>
0015
0016 #include <boost/mysql/impl/internal/coroutine.hpp>
0017 #include <boost/mysql/impl/internal/sansio/connection_state_data.hpp>
0018
0019 #include <boost/core/span.hpp>
0020
0021 #include <cstddef>
0022 #include <cstdint>
0023
0024 #ifdef BOOST_USE_VALGRIND
0025 #include <valgrind/memcheck.h>
0026 #endif
0027
0028 namespace boost {
0029 namespace mysql {
0030 namespace detail {
0031
0032
0033 #ifdef BOOST_USE_VALGRIND
0034 inline void valgrind_make_mem_defined(const void* data, std::size_t size)
0035 {
0036 VALGRIND_MAKE_MEM_DEFINED(data, size);
0037 }
0038 #else
0039 inline void valgrind_make_mem_defined(const void*, std::size_t) noexcept {}
0040 #endif
0041
0042
0043
0044
0045
0046 template <class InnerAlgo>
0047 class top_level_algo
0048 {
0049 int resume_point_{0};
0050 connection_state_data* st_;
0051 InnerAlgo algo_;
0052 span<const std::uint8_t> bytes_to_write_;
0053
0054 public:
0055 template <class... Args>
0056 top_level_algo(connection_state_data& st, Args&&... args) : st_(&st), algo_(std::forward<Args>(args)...)
0057 {
0058 }
0059
0060 const InnerAlgo& inner_algo() const { return algo_; }
0061
0062 next_action resume(error_code ec, std::size_t bytes_transferred)
0063 {
0064 next_action act;
0065
0066 switch (resume_point_)
0067 {
0068 case 0:
0069
0070
0071 while (true)
0072 {
0073
0074 act = algo_.resume(*st_, ec);
0075
0076
0077 if (act.is_done())
0078 {
0079 return act;
0080 }
0081 else if (act.type() == next_action_type::read)
0082 {
0083
0084
0085 while (!st_->reader.done() && !ec)
0086 {
0087 ec = st_->reader.prepare_buffer();
0088 if (ec)
0089 break;
0090 BOOST_MYSQL_YIELD(
0091 resume_point_,
0092 1,
0093 next_action::read({st_->reader.buffer(), st_->ssl_active()})
0094 )
0095 valgrind_make_mem_defined(st_->reader.buffer().data(), bytes_transferred);
0096 st_->reader.resume(bytes_transferred);
0097 }
0098
0099
0100 if (!ec)
0101 ec = st_->reader.error();
0102
0103
0104 }
0105 else if (act.type() == next_action_type::write)
0106 {
0107
0108 bytes_to_write_ = act.write_args().buffer;
0109
0110
0111
0112
0113
0114
0115 if (bytes_to_write_.size() > st_->max_buffer_size())
0116 {
0117 ec = client_errc::max_buffer_size_exceeded;
0118 continue;
0119 }
0120
0121 while (!bytes_to_write_.empty() && !ec)
0122 {
0123 BOOST_MYSQL_YIELD(
0124 resume_point_,
0125 2,
0126 next_action::write({bytes_to_write_, st_->ssl_active()})
0127 )
0128 bytes_to_write_ = bytes_to_write_.subspan(bytes_transferred);
0129 }
0130
0131
0132 }
0133 else
0134 {
0135
0136 BOOST_MYSQL_YIELD(resume_point_, 3, act)
0137 }
0138 }
0139 }
0140
0141 return next_action();
0142 }
0143 };
0144
0145 }
0146 }
0147 }
0148
0149 #endif