backbone.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. //----------------------------------------------------------------------------
  2. /// @file backbone.hpp
  3. /// @brief This file constains the class backbone, which is part of the
  4. /// block_indirect_sort algorithm
  5. ///
  6. /// @author Copyright (c) 2016 Francisco Jose Tapia (fjtapia@gmail.com )\n
  7. /// Distributed under the Boost Software License, Version 1.0.\n
  8. /// ( See accompanying file LICENSE_1_0.txt or copy at
  9. /// http://www.boost.org/LICENSE_1_0.txt )
  10. /// @version 0.1
  11. ///
  12. /// @remarks
  13. //-----------------------------------------------------------------------------
  14. #ifndef __BOOST_SORT_PARALLEL_DETAIL_BACKBONE_HPP
  15. #define __BOOST_SORT_PARALLEL_DETAIL_BACKBONE_HPP
  16. #include <atomic>
  17. #include <boost/sort/pdqsort/pdqsort.hpp>
  18. #include <boost/sort/common/util/atomic.hpp>
  19. #include <boost/sort/common/util/algorithm.hpp>
  20. #include <boost/sort/common/stack_cnc.hpp>
  21. #include <future>
  22. #include <iostream>
  23. #include <iterator>
  24. #include <boost/sort/block_indirect_sort/blk_detail/block.hpp>
  25. namespace boost
  26. {
  27. namespace sort
  28. {
  29. namespace blk_detail
  30. {
  31. //---------------------------------------------------------------------------
  32. // USING SENTENCES
  33. //---------------------------------------------------------------------------
  34. namespace bsc = boost::sort::common;
  35. namespace bscu = bsc::util;
  36. using bsc::stack_cnc;
  37. using bsc::range;
  38. ///---------------------------------------------------------------------------
  39. /// @struct backbone
  40. /// @brief This contains all the information shared betwen the classes of the
  41. /// block indirect sort algorithm
  42. //----------------------------------------------------------------------------
  43. template < uint32_t Block_size, class Iter_t, class Compare >
  44. struct backbone
  45. {
  46. //-------------------------------------------------------------------------
  47. // D E F I N I T I O N S
  48. //-------------------------------------------------------------------------
  49. typedef typename std::iterator_traits< Iter_t >::value_type value_t;
  50. typedef std::atomic< uint32_t > atomic_t;
  51. typedef range< size_t > range_pos;
  52. typedef range< Iter_t > range_it;
  53. typedef range< value_t * > range_buf;
  54. typedef std::function< void(void) > function_t;
  55. typedef block< Block_size, Iter_t > block_t;
  56. //------------------------------------------------------------------------
  57. // V A R I A B L E S
  58. //------------------------------------------------------------------------
  59. // range with all the element to sort
  60. range< Iter_t > global_range;
  61. // index vector of block_pos elements
  62. std::vector< block_pos > index;
  63. // Number of elements to sort
  64. size_t nelem;
  65. // Number of blocks to sort
  66. size_t nblock;
  67. // Number of elements in the last block (tail)
  68. size_t ntail;
  69. // object for to compare two elements
  70. Compare cmp;
  71. // range of elements of the last block (tail)
  72. range_it range_tail;
  73. // thread local varible. It is a pointer to the buffer
  74. static thread_local value_t *buf;
  75. // concurrent stack where store the function_t elements
  76. stack_cnc< function_t > works;
  77. // global indicator of error
  78. bool error;
  79. //
  80. //------------------------------------------------------------------------
  81. // F U N C T I O N S
  82. //------------------------------------------------------------------------
  83. backbone (Iter_t first, Iter_t last, Compare comp);
  84. //------------------------------------------------------------------------
  85. // function : get_block
  86. /// @brief obtain the block in the position pos
  87. /// @param pos : position of the range
  88. /// @return block required
  89. //------------------------------------------------------------------------
  90. block_t get_block (size_t pos) const
  91. {
  92. return block_t (global_range.first + (pos * Block_size));
  93. };
  94. //-------------------------------------------------------------------------
  95. // function : get_range
  96. /// @brief obtain the range in the position pos
  97. /// @param pos : position of the range
  98. /// @return range required
  99. //-------------------------------------------------------------------------
  100. range_it get_range (size_t pos) const
  101. {
  102. Iter_t it1 = global_range.first + (pos * Block_size);
  103. Iter_t it2 =
  104. (pos == (nblock - 1)) ? global_range.last : it1 + Block_size;
  105. return range_it (it1, it2);
  106. };
  107. //-------------------------------------------------------------------------
  108. // function : get_range_buf
  109. /// @brief obtain the auxiliary buffer of the thread
  110. //-------------------------------------------------------------------------
  111. range_buf get_range_buf ( ) const
  112. {
  113. return range_buf (buf, buf + Block_size);
  114. };
  115. //-------------------------------------------------------------------------
  116. // function : exec
  117. /// @brief Initialize the thread local buffer with the ptr_buf pointer,
  118. /// and begin with the execution of the functions stored in works
  119. //
  120. /// @param ptr_buf : Pointer to the memory assigned to the thread_local
  121. /// buffer
  122. /// @param counter : atomic counter for to invoke to the exec function
  123. /// with only 1 parameter
  124. //-------------------------------------------------------------------------
  125. void exec (value_t *ptr_buf, atomic_t &counter)
  126. {
  127. buf = ptr_buf;
  128. exec (counter);
  129. };
  130. void exec (atomic_t &counter);
  131. //---------------------------------------------------------------------------
  132. }; // end struct backbone
  133. //---------------------------------------------------------------------------
  134. //
  135. //############################################################################
  136. // ##
  137. // ##
  138. // N O N I N L I N E F U N C T I O N S ##
  139. // ##
  140. // ##
  141. //############################################################################
  142. //
  143. // initialization of the thread_local pointer to the auxiliary buffer
  144. template < uint32_t Block_size, class Iter_t, class Compare >
  145. thread_local typename std::iterator_traits< Iter_t >
  146. ::value_type *backbone< Block_size, Iter_t, Compare >::buf = nullptr;
  147. //------------------------------------------------------------------------
  148. // function : backbone
  149. /// @brief constructor of the class
  150. //
  151. /// @param first : iterator to the first element of the range to sort
  152. /// @param last : iterator after the last element to the range to sort
  153. /// @param comp : object for to compare two elements pointed by Iter_t
  154. /// iterators
  155. //------------------------------------------------------------------------
  156. template < uint32_t Block_size, class Iter_t, class Compare >
  157. backbone< Block_size, Iter_t, Compare >
  158. ::backbone (Iter_t first, Iter_t last, Compare comp)
  159. : global_range (first, last), cmp (comp), error (false)
  160. {
  161. assert ((last - first) >= 0);
  162. if (first == last) return; // nothing to do
  163. nelem = size_t (last - first);
  164. nblock = (nelem + Block_size - 1) / Block_size;
  165. ntail = (nelem % Block_size);
  166. index.reserve (nblock + 1);
  167. for (size_t i = 0; i < nblock; ++i) index.emplace_back (block_pos (i));
  168. range_tail.first =
  169. (ntail == 0) ? last : (first + ((nblock - 1) * Block_size));
  170. range_tail.last = last;
  171. };
  172. //
  173. //-------------------------------------------------------------------------
  174. // function : exec
  175. /// @brief execute the function_t stored in works, until counter is zero
  176. //
  177. /// @param counter : atomic counter. When 0 exits the function
  178. //-------------------------------------------------------------------------
  179. template < uint32_t Block_size, class Iter_t, class Compare >
  180. void backbone< Block_size, Iter_t, Compare >::exec (atomic_t &counter)
  181. {
  182. function_t func_exec;
  183. while (bscu::atomic_read (counter) != 0)
  184. {
  185. if (works.pop_move_back (func_exec)) func_exec ( );
  186. else std::this_thread::yield ( );
  187. };
  188. };
  189. //
  190. //****************************************************************************
  191. }; // End namespace blk_detail
  192. }; // End namespace sort
  193. }; // End namespace boost
  194. //****************************************************************************
  195. #endif