mdds
util.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  * Copyright (c) 2021 Kohei Yoshida
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  *
27  ************************************************************************/
28 
29 #ifndef INCLUDED_MDDS_MULTI_TYPE_VECTOR_DIR_UTIL_HPP
30 #define INCLUDED_MDDS_MULTI_TYPE_VECTOR_DIR_UTIL_HPP
31 
32 #include "./block_funcs.hpp"
33 
34 #include <sstream>
35 
36 namespace mdds { namespace mtv {
37 
43 {
53  {
54  (void)block;
55  }
56 
66  {
67  (void)block;
68  }
69 };
70 
75 {
81 
86  static constexpr lu_factor_t loop_unrolling = lu_factor_t::lu16;
87 
97 };
98 
99 namespace detail {
100 
101 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
102 
103 template<typename T, typename = void>
104 struct has_trace : std::false_type
105 {
106 };
107 
108 template<typename T>
109 struct has_trace<T, decltype((void)T::trace)> : std::true_type
110 {
111 };
112 
113 template<typename Traits>
114 struct call_trace
115 {
116  int& call_depth;
117 
118  call_trace(int& _call_depth) : call_depth(_call_depth)
119  {
120  ++call_depth;
121  }
122  ~call_trace() noexcept
123  {
124  --call_depth;
125  }
126 
127  void call(std::false_type, const ::mdds::mtv::trace_method_properties_t&) const
128  {
129  // sink
130  }
131 
132  void call(std::true_type, const ::mdds::mtv::trace_method_properties_t& props) const
133  {
134  // In case of recursive calls, only trace the first encountered method.
135  if (call_depth <= 1)
136  Traits::trace(props);
137  }
138 
139  void operator()(const ::mdds::mtv::trace_method_properties_t& props) const
140  {
141  call(has_trace<Traits>{}, props);
142  }
143 };
144 
145 #endif
146 
147 inline void throw_block_position_not_found(
148  const char* method_sig, int line, size_t pos, size_t block_size, size_t container_size)
149 {
150  std::ostringstream os;
151  os << method_sig << "#" << line << ": block position not found! (logical pos=" << pos
152  << ", block size=" << block_size << ", logical size=" << container_size << ")";
153  throw std::out_of_range(os.str());
154 }
155 
174 template<typename _T, typename _SizeT>
175 std::pair<_SizeT, bool> calc_input_end_position(const _T& it_begin, const _T& it_end, _SizeT pos, _SizeT total_size)
176 {
177  using ret_type = std::pair<_SizeT, bool>;
178 
179  _SizeT length = std::distance(it_begin, it_end);
180  if (!length)
181  // empty data array. nothing to do.
182  return ret_type(0, false);
183 
184  _SizeT end_pos = pos + length - 1;
185  if (end_pos >= total_size)
186  throw std::out_of_range("Input data sequence is too long.");
187 
188  return ret_type(end_pos, true);
189 }
190 
191 template<typename T>
192 T advance_position(const T& pos, int steps)
193 {
194  T ret = pos;
195 
196  if (steps > 0)
197  {
198  while (steps > 0)
199  {
200  if (ret.second + steps < ret.first->size)
201  {
202  // element is still in the same block.
203  ret.second += steps;
204  break;
205  }
206  else
207  {
208  steps -= static_cast<int>(ret.first->size - ret.second);
209  ++ret.first;
210  ret.second = 0;
211  }
212  }
213  }
214  else
215  {
216  while (steps < 0)
217  {
218  if (static_cast<int>(ret.second) >= -steps)
219  {
220  ret.second += steps;
221  break;
222  }
223  else
224  {
225  steps += static_cast<int>(ret.second + 1);
226  --ret.first;
227  ret.second = ret.first->size - 1;
228  }
229  }
230  }
231 
232  return ret;
233 }
234 
235 } // namespace detail
236 
237 }} // namespace mdds::mtv
238 
239 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
240 
241 #define MDDS_MTV_TRACE(method_type) \
242  ::mdds::mtv::detail::call_trace<Traits> mdds_mtv_ct(m_trace_call_depth); \
243  mdds_mtv_ct({trace_method_t::method_type, this, __func__, "", __FILE__, __LINE__})
244 
245 #define MDDS_MTV_TRACE_ARGS(method_type, stream) \
246  ::mdds::mtv::detail::call_trace<Traits> mdds_mtv_ct(m_trace_call_depth); \
247  do \
248  { \
249  std::ostringstream _os_; \
250  _os_ << stream; \
251  mdds_mtv_ct({trace_method_t::method_type, this, __func__, _os_.str(), __FILE__, __LINE__}); \
252  } while (false)
253 
254 #else
255 
256 #define MDDS_MTV_TRACE(...)
257 
258 #define MDDS_MTV_TRACE_ARGS(...)
259 
260 #endif
261 
262 #endif
263 
264 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: util.hpp:42
void element_block_acquired(const base_element_block *block)
Definition: util.hpp:52
void element_block_released(const base_element_block *block)
Definition: util.hpp:65
Definition: util.hpp:74
Definition: flat_segment_tree.hpp:46
Definition: block_funcs.hpp:64
Definition: types.hpp:159
static constexpr lu_factor_t loop_unrolling
Definition: util.hpp:86