SeqAn3
The Modern C++ library for sequence analysis.
alignment_executor_two_way.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <functional>
16 #include <optional>
17 #include <type_traits>
18 
27 #include <seqan3/std/ranges>
28 
29 namespace seqan3::detail
30 {
31 
45 template <std::ranges::ViewableRange resource_t,
46  typename alignment_algorithm_t,
47  typename execution_handler_t = execution_handler_sequential>
52 class alignment_executor_two_way
53 {
54 private:
58  using resource_type = decltype(view::single_pass_input(std::view::zip(std::declval<resource_t>(),
60  std::view::iota(0))));
62  using resource_value_type = value_type_t<resource_type>;
64 
68  using buffer_value_type = typename alignment_algorithm_t::result_type;
71  using buffer_type = std::vector<buffer_value_type>;
73  using buffer_pointer = std::ranges::iterator_t<buffer_type>;
75 
76 public:
77 
82  using value_type = buffer_value_type;
87  using difference_type = typename buffer_type::difference_type;
89 
94  alignment_executor_two_way() = delete;
95  alignment_executor_two_way(alignment_executor_two_way const &) = delete;
96  alignment_executor_two_way(alignment_executor_two_way &&) = default;
97  alignment_executor_two_way & operator=(alignment_executor_two_way const &) = delete;
98  alignment_executor_two_way & operator=(alignment_executor_two_way && ) = default;
99  ~alignment_executor_two_way() = default;
100 
111  alignment_executor_two_way(resource_t resrc,
112  alignment_algorithm_t fn) :
113  resource{std::view::zip(std::forward<resource_t>(resrc), std::view::iota(0))},
114  kernel{std::move(fn)}
115  {
117  init_buffer(std::ranges::distance(resrc));
118  else
119  init_buffer(1);
120  }
121 
132  template <typename exec_policy_t>
133  requires is_execution_policy_v<exec_policy_t>
134  alignment_executor_two_way(resource_t resrc,
135  alignment_algorithm_t fn,
136  exec_policy_t const & SEQAN3_DOXYGEN_ONLY(exec)) :
137  alignment_executor_two_way{std::move(resrc), std::move(fn)}
138  {
140  "Parallel unsequenced execution not supported!");
142  "Unsequenced execution not supported!");
143  }
145 
163  {
164  if (gptr == buffer_pointer{} || in_avail() == 0)
165  {
166  if (underflow() == eof)
167  {
168  return {std::nullopt};
169  }
170  }
171  return {std::move(*gptr++)};
172  }
173 
175  constexpr size_t in_avail() const noexcept
176  {
177  return egptr - gptr;
178  }
180 
184  bool is_eof() noexcept
186  {
187  return std::ranges::begin(resource) == std::ranges::end(resource);
188  }
190 
191 private:
192 
197  void setg(buffer_pointer beg, buffer_pointer end)
199  {
200  gptr = beg;
201  egptr = end;
202  }
203 
205  size_t underflow()
206  {
207  if (gptr < egptr) // Case: buffer not completely consumed
208  return in_avail();
209 
210  if (is_eof()) // Case: reached end of resource.
211  return eof;
212 
213  // Reset the get pointer.
214  setg(std::ranges::begin(buffer), std::ranges::end(buffer));
215 
216  // Apply the alignment execution.
217  size_t count = 0;
218  size_t buffer_limit = in_avail();
219  for (auto resource_iter = std::ranges::begin(resource);
220  count < buffer_limit && !is_eof(); ++count, ++resource_iter, ++gptr)
221  {
222  auto && [tpl, idx] = *resource_iter;
223  auto && [first_seq, second_seq] = tpl;
224  buffer_pointer write_to = gptr;
225  exec_handler.execute(kernel,
226  idx,
227  first_seq | view::all,
228  second_seq | view::all,
229  [write_to] (auto && res) { *write_to = std::move(res); });
230  }
231 
232  exec_handler.wait();
233 
234  // Update the available get position if the buffer was consumed completely.
235  setg(std::ranges::begin(buffer), std::ranges::begin(buffer) + count);
236 
237  return in_avail();
238  }
240 
248  void init_buffer(size_t const size)
249  {
250  buffer.resize(size);
251  setg(std::ranges::end(buffer), std::ranges::end(buffer));
252  }
254 
256  static constexpr size_t eof{std::numeric_limits<size_t>::max()};
257 
259  execution_handler_t exec_handler{};
260 
262  resource_type resource{};
264  alignment_algorithm_t kernel{};
265 
267  buffer_type buffer{};
269  buffer_pointer gptr{};
271  buffer_pointer egptr{};
272 };
273 
279 template <typename resource_rng_t, typename func_t>
281 alignment_executor_two_way(resource_rng_t &&, func_t) ->
282  alignment_executor_two_way<resource_rng_t, func_t, execution_handler_sequential>;
283 
285 template <typename resource_rng_t, typename func_t, typename exec_policy_t>
286  requires is_execution_policy_v<exec_policy_t>
287 alignment_executor_two_way(resource_rng_t &&, func_t, exec_policy_t const &) ->
288  alignment_executor_two_way<resource_rng_t,
289  func_t,
291  execution_handler_parallel,
292  execution_handler_sequential>>;
293 
295 } // namespace seqan3::detail
::ranges::distance distance
Alias for ranges::distance. Returns the number of hops from first to last.
Definition: iterator:321
auto constexpr is_eof
Checks whether a given letter is equal to the EOF constant defined in <cstdio>.
Definition: predicate.hpp:95
constexpr auto zip
A range adaptor that transforms a tuple of range into a range of tuples.
Definition: ranges:948
Provides execution policies.
Provides various shortcuts for common std::ranges functions.
The concept std::CopyConstructible is satisfied if T is an lvalue reference type, or if it is a MoveC...
constexpr auto all
A view adaptor that behaves like std::view:all, but type erases contiguous ranges.
Definition: view_all.hpp:160
::ranges::size size
Alias for ranges::size. Obtains the size of a range whose size can be calculated in constant time...
Definition: ranges:189
::ranges::iterator_t iterator_t
Alias for ranges::iterator_t. Obtains the iterator type of a range.
Definition: ranges:204
Adaptations of concepts from the Ranges TS.
::ranges::begin begin
Alias for ranges::begin. Returns an iterator to the beginning of a range.
Definition: ranges:174
Provides seqan3::view::all.
Provides seqan3::detail::alignment_range.
constexpr auto iota
Generates a sequence of elements by repeatedly incrementing an initial value.
Definition: ranges:647
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
T max(T... args)
Specifies the requirements of a Range type that is either a std::ranges::View or an lvalue-reference...
T count(T... args)
Specifies requirements of a Range type for which begin returns a type that models std::ForwardIterato...
constexpr auto single_pass_input
A view adapter that decays most of the range properties and adds single pass behavior.
Definition: single_pass_input.hpp:381
Definition: aligned_sequence_concept.hpp:35
Provides seqan3::detail::execution_handler_parallel.
Provides various transformation traits used by the range module.
Provides seqan3::single_pass_input_view.
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:179
Provides seqan3::detail::execution_handler_sequential.