20namespace seqan3::detail
51template <std::ranges::viewable_range resource_t,
52 std::semiregular algorithm_t,
53 std::semiregular algorithm_result_t,
54 typename execution_handler_t = execution_handler_sequential>
55 requires std::ranges::forward_range<resource_t>
56 && std::invocable<algorithm_t,
57 std::ranges::range_reference_t<resource_t>,
59class algorithm_executor_blocking
66 using resource_type = std::views::all_t<resource_t>;
68 using resource_iterator_type = std::ranges::iterator_t<resource_type>;
79 using bucket_iterator_type = std::ranges::iterator_t<bucket_type>;
83 using buffer_iterator_type = std::ranges::iterator_t<buffer_type>;
100 algorithm_executor_blocking() =
delete;
102 algorithm_executor_blocking(algorithm_executor_blocking
const &) =
delete;
121 algorithm_executor_blocking(algorithm_executor_blocking && other) noexcept :
122 algorithm_executor_blocking{std::move(other), other.resource_position()}
126 algorithm_executor_blocking & operator=(algorithm_executor_blocking
const &) =
delete;
130 algorithm_executor_blocking & operator=(algorithm_executor_blocking && other)
132 auto old_resource_position = other.resource_position();
134 resource = std::move(other.resource);
135 move_initialise(std::move(other), old_resource_position);
140 ~algorithm_executor_blocking() =
default;
156 algorithm_executor_blocking(resource_t resource,
157 algorithm_t algorithm,
158 algorithm_result_t
const SEQAN3_DOXYGEN_ONLY(result) = algorithm_result_t{},
159 execution_handler_t && exec_handler = execution_handler_t{}) :
160 exec_handler{
std::
move(exec_handler)},
162 resource_it{
std::ranges::
begin(this->resource)},
163 algorithm{
std::
move(algorithm)}
165 if constexpr (std::same_as<execution_handler_t, execution_handler_parallel>)
166 buffer_size =
static_cast<size_t>(std::ranges::distance(this->resource));
168 buffer.resize(buffer_size);
169 buffer_it = buffer.end();
170 buffer_end_it = buffer_it;
198 while (status == fill_status::empty_buffer);
200 if (status == fill_status::end_of_resource)
201 return {std::nullopt};
203 assert(status == fill_status::non_empty_buffer);
204 assert(bucket_it != buffer_it->end());
214 return resource_it == std::ranges::end(resource);
223 algorithm_executor_blocking(algorithm_executor_blocking && other,
224 resource_difference_type old_resource_position) noexcept :
225 resource{std::move(other.resource)}
227 move_initialise(std::move(other), old_resource_position);
236 resource_difference_type resource_position()
240 assert(position >= 0);
245 fill_status fill_buffer()
247 if (!is_buffer_empty())
248 return fill_status::non_empty_buffer;
251 return fill_status::end_of_resource;
257 for (buffer_end_it = buffer_it; buffer_end_it != buffer.end() && !
is_eof(); ++buffer_end_it, ++resource_it)
259 exec_handler.execute(algorithm,
261 [target_buffer_it = buffer_end_it](
auto && algorithm_result)
263 target_buffer_it->push_back(std::move(algorithm_result));
270 find_next_non_empty_bucket();
272 if (is_buffer_empty())
273 return fill_status::empty_buffer;
275 return fill_status::non_empty_buffer;
281 bool is_buffer_empty()
const
283 return buffer_it == buffer_end_it;
297 for (
auto & bucket : buffer)
301 buffer_it = buffer.begin();
312 void find_next_non_empty_bucket()
314 assert(buffer_it <= buffer_end_it);
318 [](
auto const & buffer)
320 return !buffer.empty();
323 if (buffer_it != buffer_end_it)
324 bucket_it = buffer_it->begin();
334 void go_to_next_result()
336 if (++bucket_it == buffer_it->end())
339 find_next_non_empty_bucket();
344 void move_initialise(algorithm_executor_blocking && other, resource_difference_type old_resource_position)
noexcept
346 algorithm = std::move(other.algorithm);
347 buffer_size = std::move(other.buffer_size);
348 exec_handler = std::move(other.exec_handler);
353 auto buffer_it_position = other.buffer_it - other.buffer.begin();
354 auto buffer_end_it_position = other.buffer_end_it - other.buffer.begin();
357 if (buffer_it_position != buffer_end_it_position)
358 bucket_it_position = other.bucket_it - other.buffer_it->begin();
361 buffer = std::move(other.buffer);
362 buffer_it = buffer.begin() + buffer_it_position;
363 buffer_end_it = buffer.begin() + buffer_end_it_position;
365 if (buffer_it_position != buffer_end_it_position)
366 bucket_it = buffer_it->begin() + bucket_it_position;
370 execution_handler_t exec_handler{};
373 resource_type resource;
375 resource_iterator_type resource_it{};
377 algorithm_t algorithm{};
380 buffer_type buffer{};
382 buffer_iterator_type buffer_it{};
384 buffer_iterator_type buffer_end_it{};
386 bucket_iterator_type bucket_it{};
388 size_t buffer_size{1};
397template <
typename resource_rng_t, std::semiregular algorithm_t, std::semiregular algorithm_result_t>
398algorithm_executor_blocking(resource_rng_t &&, algorithm_t, algorithm_result_t
const &)
399 -> algorithm_executor_blocking<resource_rng_t, algorithm_t, algorithm_result_t, execution_handler_sequential>;
Provides seqan3::detail::execution_handler_parallel.
Provides seqan3::detail::execution_handler_sequential.
constexpr auto is_eof
Checks whether a given letter is equal to the EOF constant defined in <cstdio>.
Definition predicate.hpp:72
SeqAn specific customisations in the standard namespace.