Skip to content

Commit 9f5df22

Browse files
committed
refactor read operations
1 parent 4754861 commit 9f5df22

File tree

4 files changed

+237
-153
lines changed

4 files changed

+237
-153
lines changed

CMakeLists.txt

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ if (BOOST_HTTP_IO_IS_ROOT)
3737
endif ()
3838
option(BOOST_HTTP_IO_BUILD_TESTS "Build boost::http_io tests" ${BUILD_TESTING})
3939
option(BOOST_HTTP_IO_BUILD_EXAMPLES "Build boost::http_io examples" ${BOOST_HTTP_IO_IS_ROOT})
40+
option(BOOST_HTTP_IO_MRDOCS_BUILD "Build the target for MrDocs: see mrdocs.yml" OFF)
4041

4142

4243
# Check if environment variable BOOST_SRC_DIR is set
@@ -138,23 +139,36 @@ source_group("" FILES "include/boost/http_io.hpp" "build/Jamfile")
138139
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/include/boost/http_io PREFIX "include" FILES ${BOOST_HTTP_IO_HEADERS})
139140
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/src PREFIX "src" FILES ${BOOST_HTTP_IO_SOURCES})
140141

142+
143+
function(boost_http_io_setup_properties target)
144+
target_compile_features(${target} PUBLIC cxx_constexpr)
145+
target_include_directories(${target} PUBLIC "${PROJECT_SOURCE_DIR}/include")
146+
target_link_libraries(${target} PUBLIC ${BOOST_HTTP_IO_DEPENDENCIES})
147+
find_package(Threads REQUIRED)
148+
target_link_libraries(${target} PUBLIC Threads::Threads)
149+
if (MINGW)
150+
target_link_libraries(${target} PUBLIC ws2_32 wsock32)
151+
endif()
152+
target_compile_definitions(${target} PUBLIC BOOST_HTTP_IO_NO_LIB)
153+
target_compile_definitions(${target} PRIVATE BOOST_HTTP_IO_SOURCE)
154+
if (BUILD_SHARED_LIBS)
155+
target_compile_definitions(${target} PUBLIC BOOST_HTTP_IO_DYN_LINK)
156+
else ()
157+
target_compile_definitions(${target} PUBLIC BOOST_HTTP_IO_STATIC_LINK)
158+
endif ()
159+
endfunction()
160+
161+
if (BOOST_HTTP_IO_MRDOCS_BUILD)
162+
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/mrdocs.cpp" "#include <boost/http_io.hpp>\n")
163+
add_library(boost_http_io_mrdocs "${CMAKE_CURRENT_BINARY_DIR}/mrdocs.cpp")
164+
boost_http_io_setup_properties(boost_http_io_mrdocs)
165+
boost_http_io_setup_properties(boost_http_io_mrdocs PUBLIC BOOST_HTTP_IO_MRDOCS)
166+
return()
167+
endif()
168+
141169
add_library(boost_http_io include/boost/http_io.hpp build/Jamfile ${BOOST_HTTP_IO_HEADERS} ${BOOST_HTTP_IO_SOURCES})
142170
add_library(Boost::http_io ALIAS boost_http_io)
143-
target_compile_features(boost_http_io PUBLIC cxx_constexpr)
144-
target_include_directories(boost_http_io PUBLIC "${PROJECT_SOURCE_DIR}/include")
145-
target_link_libraries(boost_http_io PUBLIC ${BOOST_HTTP_IO_DEPENDENCIES})
146-
find_package(Threads REQUIRED)
147-
target_link_libraries(boost_http_io PUBLIC Threads::Threads)
148-
if (MINGW)
149-
target_link_libraries(boost_http_io PUBLIC ws2_32 wsock32)
150-
endif()
151-
target_compile_definitions(boost_http_io PUBLIC BOOST_HTTP_IO_NO_LIB)
152-
target_compile_definitions(boost_http_io PRIVATE BOOST_HTTP_IO_SOURCE)
153-
if (BUILD_SHARED_LIBS)
154-
target_compile_definitions(boost_http_io PUBLIC BOOST_HTTP_IO_DYN_LINK)
155-
else ()
156-
target_compile_definitions(boost_http_io PUBLIC BOOST_HTTP_IO_STATIC_LINK)
157-
endif ()
171+
boost_http_io_setup_properties(boost_http_io)
158172

159173
#-------------------------------------------------
160174
#

doc/mrdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ multipage: true
2626
use-system-libc: true
2727
use-system-stdlib: true
2828

29-
cmake: '-DCMAKE_CXX_STANDARD=20 -DBOOST_HTTP_IO_BUILD_TESTS=OFF -DBOOST_HTTP_IO_BUILD_EXAMPLES=OFF'
29+
cmake: '-DCMAKE_CXX_STANDARD=20 -DBOOST_HTTP_IO_MRDOCS_BUILD=ON -DBOOST_HTTP_IO_BUILD_TESTS=OFF -DBOOST_HTTP_IO_BUILD_EXAMPLES=OFF'

include/boost/http_io/impl/read.hpp

Lines changed: 49 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,22 @@ namespace http_io {
2525
namespace detail {
2626

2727
template<class AsyncStream>
28-
class read_header_op
28+
class read_until_op
2929
: public asio::coroutine
3030
{
3131
AsyncStream& stream_;
3232
http_proto::parser& pr_;
3333
std::size_t total_bytes_ = 0;
34+
bool (&condition_)(http_proto::parser&);
3435

3536
public:
36-
read_header_op(
37+
read_until_op(
3738
AsyncStream& s,
38-
http_proto::parser& pr) noexcept
39+
http_proto::parser& pr,
40+
bool (&condition)(http_proto::parser&)) noexcept
3941
: stream_(s)
4042
, pr_(pr)
43+
, condition_(condition)
4144
{
4245
}
4346

@@ -50,20 +53,34 @@ class read_header_op
5053
{
5154
BOOST_ASIO_CORO_REENTER(*this)
5255
{
53-
if(pr_.got_header())
56+
self.reset_cancellation_state(
57+
asio::enable_total_cancellation());
58+
59+
for(;;)
5460
{
55-
BOOST_ASIO_CORO_YIELD
61+
for(;;)
5662
{
57-
BOOST_ASIO_HANDLER_LOCATION((
58-
__FILE__, __LINE__,
59-
"immediate"));
60-
asio::async_immediate(
61-
self.get_io_executor(), std::move(self));
63+
pr_.parse(ec);
64+
if(ec == http_proto::condition::need_more_input)
65+
break;
66+
if(ec.failed() || condition_(pr_))
67+
{
68+
if(total_bytes_ == 0)
69+
{
70+
BOOST_ASIO_CORO_YIELD
71+
{
72+
BOOST_ASIO_HANDLER_LOCATION((
73+
__FILE__, __LINE__,
74+
"immediate"));
75+
auto io_ex = self.get_io_executor();
76+
asio::async_immediate(
77+
io_ex,
78+
asio::append(std::move(self), ec));
79+
}
80+
}
81+
goto upcall;
82+
}
6283
}
63-
goto upcall;
64-
}
65-
for(;;)
66-
{
6784
BOOST_ASIO_CORO_YIELD
6885
{
6986
BOOST_ASIO_HANDLER_LOCATION((
@@ -86,14 +103,6 @@ class read_header_op
86103
{
87104
goto upcall;
88105
}
89-
pr_.parse(ec);
90-
if(ec != http_proto::condition::need_more_input)
91-
break;
92-
if(pr_.got_header())
93-
{
94-
ec = {}; // override possible need_more_input
95-
break;
96-
}
97106
}
98107

99108
upcall:
@@ -102,97 +111,19 @@ class read_header_op
102111
}
103112
};
104113

105-
//------------------------------------------------
106-
107-
template<class AsyncStream>
108-
class read_body_op
109-
: public asio::coroutine
114+
inline
115+
bool
116+
got_header_condition(http_proto::parser& pr)
110117
{
111-
AsyncStream& stream_;
112-
http_proto::parser& pr_;
113-
std::size_t total_bytes_ = 0;
114-
bool some_;
115-
116-
public:
117-
read_body_op(
118-
AsyncStream& s,
119-
http_proto::parser& pr,
120-
bool some)
121-
: stream_(s)
122-
, pr_(pr)
123-
, some_(some)
124-
{
125-
}
126-
127-
template<class Self>
128-
void
129-
operator()(
130-
Self& self,
131-
system::error_code ec = {},
132-
std::size_t bytes_transferred = 0)
133-
{
134-
BOOST_ASIO_CORO_REENTER(*this)
135-
{
136-
pr_.parse(ec);
137-
if(ec != http_proto::condition::need_more_input)
138-
{
139-
BOOST_ASIO_CORO_YIELD
140-
{
141-
BOOST_ASIO_HANDLER_LOCATION((
142-
__FILE__, __LINE__,
143-
"immediate"));
144-
auto io_ex = self.get_io_executor();
145-
asio::async_immediate(
146-
io_ex,
147-
asio::append(std::move(self), ec));
148-
}
149-
goto upcall;
150-
}
151-
for(;;)
152-
{
153-
BOOST_ASIO_CORO_YIELD
154-
{
155-
BOOST_ASIO_HANDLER_LOCATION((
156-
__FILE__, __LINE__,
157-
"async_read_some"));
158-
stream_.async_read_some(
159-
pr_.prepare(),
160-
std::move(self));
161-
}
162-
pr_.commit(bytes_transferred);
163-
total_bytes_ += bytes_transferred;
164-
if(ec == asio::error::eof)
165-
{
166-
BOOST_ASSERT(
167-
bytes_transferred == 0);
168-
pr_.commit_eof();
169-
ec = {};
170-
}
171-
else if(ec.failed())
172-
{
173-
goto upcall;
174-
}
175-
pr_.parse(ec);
176-
if(! ec.failed())
177-
{
178-
BOOST_ASSERT(
179-
pr_.is_complete());
180-
break;
181-
}
182-
if(ec != http_proto::condition::need_more_input)
183-
break;
184-
if(some_)
185-
{
186-
ec = {};
187-
break;
188-
}
189-
}
118+
return pr.got_header();
119+
}
190120

191-
upcall:
192-
self.complete(ec, total_bytes_);
193-
}
194-
}
195-
};
121+
inline
122+
bool
123+
is_complete_condition(http_proto::parser& pr)
124+
{
125+
return pr.is_complete();
126+
}
196127

197128
} // detail
198129

@@ -204,16 +135,16 @@ template<
204135
void(system::error_code, std::size_t)) CompletionToken>
205136
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
206137
void (system::error_code, std::size_t))
207-
async_read_header(
138+
async_read_some(
208139
AsyncReadStream& s,
209140
http_proto::parser& pr,
210141
CompletionToken&& token)
211142
{
212143
return asio::async_compose<
213144
CompletionToken,
214145
void(system::error_code, std::size_t)>(
215-
detail::read_header_op<
216-
AsyncReadStream>{s, pr},
146+
detail::read_until_op<AsyncReadStream>
147+
{s, pr, detail::got_header_condition},
217148
token,
218149
s);
219150
}
@@ -224,22 +155,12 @@ template<
224155
void(system::error_code, std::size_t)) CompletionToken>
225156
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
226157
void (system::error_code, std::size_t))
227-
async_read_some(
158+
async_read_header(
228159
AsyncReadStream& s,
229160
http_proto::parser& pr,
230161
CompletionToken&& token)
231162
{
232-
// header must be read first!
233-
if(! pr.got_header())
234-
detail::throw_logic_error();
235-
236-
return asio::async_compose<
237-
CompletionToken,
238-
void(system::error_code, std::size_t)>(
239-
detail::read_body_op<
240-
AsyncReadStream>{s, pr, true},
241-
token,
242-
s);
163+
return async_read_some(s, pr, std::move(token));
243164
}
244165

245166
template<
@@ -253,15 +174,11 @@ async_read(
253174
http_proto::parser& pr,
254175
CompletionToken&& token)
255176
{
256-
// header must be read first!
257-
if(! pr.got_header())
258-
detail::throw_logic_error();
259-
260177
return asio::async_compose<
261178
CompletionToken,
262179
void(system::error_code, std::size_t)>(
263-
detail::read_body_op<
264-
AsyncReadStream>{s, pr, false},
180+
detail::read_until_op<AsyncReadStream>
181+
{s, pr, detail::is_complete_condition},
265182
token,
266183
s);
267184
}

0 commit comments

Comments
 (0)