15 #include <restinio/impl/include_fmtlib.hpp> 17 #include <restinio/utils/suppress_exceptions.hpp> 19 #include <restinio/exception.hpp> 20 #include <restinio/request_handler.hpp> 21 #include <restinio/buffers.hpp> 22 #include <restinio/optional.hpp> 44 return ctx.m_write_groups;
51 request_id_t request_id )
noexcept 53 m_request_id = request_id;
54 m_response_output_flags =
55 response_output_flags_t{
56 response_parts_attr_t::not_final_parts,
57 response_connection_attr_t::connection_keepalive };
66 if( !m_write_groups.empty() &&
67 !m_write_groups.back().has_after_write_notificator() &&
68 std::size_t{ 0 } == wg.status_line_size() )
70 m_write_groups.back().merge( std::move( wg ) );
74 m_write_groups.emplace_back( std::move( wg ) );
80 bool empty()
const noexcept {
return m_write_groups.empty(); }
86 assert( !m_write_groups.empty() );
89 RESTINIO_STATIC_ASSERT_NOEXCEPT(
90 write_group_t{ std::declval<write_group_t>() } );
92 write_group_t result{ std::move( m_write_groups.front() ) };
97 static_if_else<
noexcept(m_write_groups.erase(m_write_groups.begin())) >(
100 m_write_groups.erase( m_write_groups.begin() );
104 restinio::utils::suppress_exceptions_quietly( [
this] {
105 m_write_groups.erase( m_write_groups.begin() );
119 m_response_output_flags = flags;
126 return m_response_output_flags;
133 return m_write_groups.empty() &&
134 response_parts_attr_t::final_parts ==
135 m_response_output_flags.m_response_parts;
161 m_contexts.resize( max_elements_count );
168 return !m_elements_exists;
175 return m_contexts.size() == m_elements_exists;
182 return m_contexts[ m_first_element_index ];
190 (m_first_element_index + (m_elements_exists - 1) ) %
199 req_id < front().request_id() ||
200 req_id > back().request_id() )
205 return &m_contexts[ get_real_index( req_id ) ];
214 "unable to insert context because " 215 "response_context_table is full" };
220 ( m_first_element_index + m_elements_exists ) % m_contexts.size()
223 ctx.reinit( req_id );
235 "unable to pop context because " 236 "response_context_table is empty" };
255 ++m_first_element_index;
256 if( m_contexts.size() == m_first_element_index )
258 m_first_element_index = std::size_t{0};
266 const auto distance_from_first =
267 req_id - front().request_id();
269 return ( m_first_element_index + distance_from_first ) % m_contexts.size();
293 std::size_t max_req_count )
302 bool empty()
const noexcept {
return m_context_table.empty(); }
303 bool is_full()
const noexcept {
return m_context_table.is_full(); }
317 m_context_table.push_response_context( m_request_id_counter );
319 return m_request_id_counter++;
328 response_output_flags_t response_output_flags,
335 "unable to append response parts, " 336 "response coordinator is closed" };
338 auto * ctx = m_context_table.get_by_req_id( req_id );
345 "no context associated with request {}",
349 if( response_parts_attr_t::final_parts ==
350 ctx->response_output_flags().m_response_parts )
354 "unable to append response, " 355 "it marked as complete" };
358 ctx->response_output_flags( response_output_flags );
360 ctx->enqueue_group( std::move( wg ) );
375 "unable to prepare output buffers, " 376 "response coordinator is closed" };
response_context_t & back() noexcept
Get last context.
std::size_t get_real_index(request_id_t req_id) noexcept
A context for a single response.
std::size_t m_elements_exists
bool is_full() const noexcept
response_output_flags_t m_response_output_flags
Response flags.
void reset() noexcept
Remove all contexts.
bool m_connection_closed_response_occured
Indicate whether a response with connection close flag was emitted.
void pop_response_context_nonchecked() noexcept
Remove the first context from queue with the check for emptiness of the queue.
bool is_complete() const noexcept
Is response data of a given request is complete.
response_context_t * get_by_req_id(request_id_t req_id) noexcept
Get context of specified request.
bool empty() const noexcept
bool empty() const noexcept
If table is empty.
void append_response(request_id_t req_id, response_output_flags_t response_output_flags, write_group_t wg)
Add outgoing data for specified request.
bool empty() const noexcept
Is context empty.
auto request_id() const noexcept
Get id of associated request.
auto response_output_flags() const noexcept
Get flags of corrent response data flow.
response_coordinator_t(std::size_t max_req_count)
std::vector< response_context_t > m_contexts
void reinit(request_id_t request_id) noexcept
Reinitialize context.
void response_output_flags(response_output_flags_t flags) noexcept
Get flags of corrent response data flow.
friend write_groups_container_t & utest_access(response_context_t &ctx)
Access write-groups container (used in unit tests)
void push_response_context(request_id_t req_id)
Insert new context into queue.
response_context_t & front() noexcept
Get first context.
Helper storage for responses' contexts.
bool closed() const noexcept
RESTINIO_NODISCARD char to_lower_case(unsigned char ch)
std::size_t m_first_element_index
response_context_table_t(std::size_t max_elements_count)
request_id_t register_new_request()
Create a new request and reserve context for its response.
write_groups_container_t m_write_groups
Unsent responses parts.
void enqueue_group(write_group_t wg)
Put write group to data queue.
response_context_table_t m_context_table
A storage for resp-context items.
void pop_response_context()
Remove the first context from queue.
write_group_t dequeue_group() noexcept
Extract write group from data queue.
request_id_t m_request_id
bool is_able_to_get_more_messages() const noexcept
Check if it is possible to accept more requests.
bool is_full() const noexcept
If table is full.
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, optional_t< Value_Type > >::type opt_value(const Parameter_Container ¶ms, string_view_t key)
Gets the value of a parameter specified by key wrapped in optional_t<Value_Type> if parameter exists ...