deque_cnc.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. //----------------------------------------------------------------------------
  2. /// @file deque_cnc.hpp
  3. /// @brief This file contains the implementation of the several types of
  4. /// recursive fastmutex for read and write
  5. ///
  6. /// @author Copyright (c) 2010 2015 Francisco José Tapia ([email protected] )\n
  7. /// Distributed under the Boost Software License, Version 1.0.\n
  8. /// ( See accompanyingfile 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 __TOOLS_DEQUE_CNC_HPP
  15. #define __TOOLS_DEQUE_CNC_HPP
  16. #include <ciso646>
  17. #include <vector>
  18. #include <deque>
  19. #include <boost/sort/common/spinlock.hpp>
  20. namespace boost
  21. {
  22. namespace sort
  23. {
  24. namespace common
  25. {
  26. //###########################################################################
  27. // ##
  28. // ################################################################ ##
  29. // # # ##
  30. // # C L A S S # ##
  31. // # S T A C K _ C N C # ##
  32. // # # ##
  33. // ################################################################ ##
  34. // ##
  35. //###########################################################################
  36. //
  37. //---------------------------------------------------------------------------
  38. /// @class deque_cnc
  39. /// @brief This class is a concurrent stack controled by a spin_lock
  40. /// @remarks
  41. //---------------------------------------------------------------------------
  42. template<typename T, typename Allocator = std::allocator<T> >
  43. class deque_cnc
  44. {
  45. public:
  46. //-----------------------------------------------------------------------
  47. // D E F I N I T I O N S
  48. //-----------------------------------------------------------------------
  49. typedef std::deque<T, Allocator> deque_t;
  50. typedef typename deque_t::size_type size_type;
  51. typedef typename deque_t::difference_type difference_type;
  52. typedef typename deque_t::value_type value_type;
  53. typedef typename deque_t::pointer pointer;
  54. typedef typename deque_t::const_pointer const_pointer;
  55. typedef typename deque_t::reference reference;
  56. typedef typename deque_t::const_reference const_reference;
  57. typedef typename deque_t::allocator_type allocator_type;
  58. protected:
  59. //------------------------------------------------------------------------
  60. // VARIABLES
  61. //------------------------------------------------------------------------
  62. deque_t dq;
  63. mutable spinlock_t spl;
  64. public:
  65. //
  66. //-----------------------------------------------------------------------
  67. // C O N S T R U C T O R S A N D D E S T R U C T O R
  68. //-----------------------------------------------------------------------
  69. //
  70. //-----------------------------------------------------------------------
  71. // function : deque_cnc
  72. /// @brief constructor
  73. //----------------------------------------------------------------------
  74. explicit inline deque_cnc(void): dq() { };
  75. //
  76. //----------------------------------------------------------------------
  77. // function : deque_cnc
  78. /// @brief constructor
  79. /// @param [in] ALLC : Allocator
  80. //----------------------------------------------------------------------
  81. explicit inline deque_cnc(const Allocator &ALLC): dq(ALLC){ };
  82. //
  83. //----------------------------------------------------------------------
  84. // function : ~deque_cnc
  85. /// @brief Destructor
  86. //----------------------------------------------------------------------
  87. virtual ~deque_cnc(void){ dq.clear(); };
  88. //
  89. //----------------------------------------------------------------------
  90. // function : clear
  91. /// @brief Delete all the elements of the deque_cnc.
  92. //----------------------------------------------------------------------
  93. void clear(void)
  94. {
  95. std::lock_guard < spinlock_t > S(spl);
  96. dq.clear();
  97. };
  98. //
  99. //------------------------------------------------------------------------
  100. // function : swap
  101. /// @brief swap the data between the two deque_cnc
  102. /// @param [in] A : deque_cnc to swap
  103. /// @return none
  104. //-----------------------------------------------------------------------
  105. void swap(deque_cnc & A) noexcept
  106. {
  107. if (this == &A) return;
  108. std::lock_guard < spinlock_t > S(spl);
  109. dq.swap(A.dq);
  110. };
  111. //
  112. //-----------------------------------------------------------------------
  113. // S I Z E , M A X _ S I Z E , R E S I Z E
  114. // C A P A C I T Y , E M P T Y , R E S E R V E
  115. //-----------------------------------------------------------------------
  116. //
  117. //------------------------------------------------------------------------
  118. // function : size
  119. /// @brief return the number of elements in the deque_cnc
  120. /// @return number of elements in the deque_cnc
  121. //------------------------------------------------------------------------
  122. size_type size(void) const noexcept
  123. {
  124. std::lock_guard < spinlock_t > S(spl);
  125. return dq.size();
  126. };
  127. //
  128. //------------------------------------------------------------------------
  129. // function :max_size
  130. /// @brief return the maximun size of the container
  131. /// @return maximun size of the container
  132. //------------------------------------------------------------------------
  133. size_type max_size(void) const noexcept
  134. {
  135. std::lock_guard < spinlock_t > S(spl);
  136. return (dq.max_size());
  137. };
  138. //
  139. //-------------------------------------------------------------------------
  140. // function : shrink_to_fit
  141. /// @brief resize the current vector size and change to size.\n
  142. /// If sz is smaller than the current size, delete elements to end\n
  143. /// If sz is greater than the current size, insert elements to the
  144. /// end with the value c
  145. /// @param [in] sz : new size of the deque_cnc after the resize
  146. /// @param [in] c : Value to insert if sz is greather than the current size
  147. /// @return none
  148. //------------------------------------------------------------------------
  149. void shrink_to_fit()
  150. {
  151. std::lock_guard < spinlock_t > S(spl);
  152. dq.shrink_to_fit();
  153. };
  154. //
  155. //------------------------------------------------------------------------
  156. // function : empty
  157. /// @brief indicate if the map is empty
  158. /// @return true if the map is empty, false in any other case
  159. //------------------------------------------------------------------------
  160. bool empty(void) const noexcept
  161. {
  162. std::lock_guard < spinlock_t > S(spl);
  163. return (dq.empty());
  164. };
  165. //---------------------------------------------------------------------------
  166. // function : push_back
  167. /// @brief Insert one element in the back of the container
  168. /// @param [in] D : value to insert. Can ve a value, a reference or an
  169. /// rvalue
  170. //---------------------------------------------------------------------------
  171. void push_back(const value_type & D)
  172. {
  173. std::lock_guard < spinlock_t > S(spl);
  174. dq.push_back(D);
  175. };
  176. //------------------------------------------------------------------------
  177. // function : emplace_back
  178. /// @brief Insert one element in the back of the container
  179. /// @param [in] args :group of arguments for to build the object to insert
  180. //-------------------------------------------------------------------------
  181. template<class ... Args>
  182. void emplace_back(Args && ... args)
  183. {
  184. std::lock_guard < spinlock_t > S(spl);
  185. dq.emplace_back(std::forward <Args>(args) ...);
  186. };
  187. //------------------------------------------------------------------------
  188. // function : push_back
  189. /// @brief Insert one element in the back of the container
  190. /// @param [in] D : deque to insert in the actual deque, inserting a copy
  191. /// of the elements
  192. /// @return reference to the deque after the insertion
  193. //------------------------------------------------------------------------
  194. template<class Allocator2>
  195. deque_cnc & push_back(const std::deque<value_type, Allocator2> & D)
  196. {
  197. std::lock_guard < spinlock_t > S(spl);
  198. for (size_type i = 0; i < D.size(); ++i)
  199. dq.push_back(D[i]);
  200. return *this;
  201. };
  202. //------------------------------------------------------------------------
  203. // function : push_back
  204. /// @brief Insert one element in the back of the container
  205. /// @param [in] D : deque to insert in the actual deque, inserting a move
  206. /// of the elements
  207. /// @return reference to the deque after the insertion
  208. //------------------------------------------------------------------------
  209. deque_cnc & push_back(std::deque<value_type, Allocator> && D)
  210. {
  211. std::lock_guard < spinlock_t > S(spl);
  212. for (size_type i = 0; i < D.size(); ++i)
  213. dq.emplace_back(std::move(D[i]));
  214. return *this;
  215. };
  216. //
  217. //------------------------------------------------------------------------
  218. // function :pop_back
  219. /// @brief erase the last element of the container
  220. //-----------------------------------------------------------------------
  221. void pop_back(void)
  222. {
  223. std::lock_guard < spinlock_t > S(spl);
  224. dq.pop_back();
  225. };
  226. //
  227. //------------------------------------------------------------------------
  228. // function :pop_copy_back
  229. /// @brief erase the last element and return a copy over P
  230. /// @param [out] P : reference to a variable where copy the element
  231. /// @return code of the operation
  232. /// true - Element erased
  233. /// false - Empty tree
  234. //------------------------------------------------------------------------
  235. bool pop_copy_back(value_type & P)
  236. { //-------------------------- begin -----------------------------
  237. std::lock_guard < spinlock_t > S(spl);
  238. if (dq.size() == 0) return false;
  239. P = dq.back();
  240. dq.pop_back();
  241. return true;
  242. };
  243. //
  244. //------------------------------------------------------------------------
  245. // function :pop_move_back
  246. /// @brief erase the last element and move over P
  247. /// @param [out] P : reference to a variable where move the element
  248. /// @return code of the operation
  249. /// true - Element erased
  250. /// false - Empty tree
  251. //------------------------------------------------------------------------
  252. bool pop_move_back(value_type & P)
  253. { //-------------------------- begin -----------------------------
  254. std::lock_guard < spinlock_t > S(spl);
  255. if (dq.size() == 0) return false;
  256. P = std::move(dq.back());
  257. dq.pop_back();
  258. return true;
  259. };
  260. //------------------------------------------------------------------------
  261. // function : push_front
  262. /// @brief Insert one copy of the element in the front of the container
  263. /// @param [in] D : value to insert
  264. //------------------------------------------------------------------------
  265. void push_front(const value_type & D)
  266. {
  267. std::lock_guard < spinlock_t > S(spl);
  268. dq.push_front(D);
  269. };
  270. //------------------------------------------------------------------------
  271. // function : emplace_front
  272. /// @brief Insert one element in the front of the container
  273. /// @param [in] args :group of arguments for to build the object to insert
  274. //-------------------------------------------------------------------------
  275. template<class ... Args>
  276. void emplace_front(Args && ... args)
  277. {
  278. std::lock_guard < spinlock_t > S(spl);
  279. dq.emplace_front(std::forward <Args>(args) ...);
  280. };
  281. //------------------------------------------------------------------------
  282. // function : push_front
  283. /// @brief Insert a copy of the elements of the deque V1 in the front
  284. /// of the container
  285. /// @param [in] V1 : deque with the elements to insert
  286. /// @return reference to the deque after the insertion
  287. //------------------------------------------------------------------------
  288. template<class Allocator2>
  289. deque_cnc & push_front(const std::deque<value_type, Allocator2> & V1)
  290. {
  291. std::lock_guard < spinlock_t > S(spl);
  292. for (size_type i = 0; i < V1.size(); ++i)
  293. dq.push_front(V1[i]);
  294. return *this;
  295. };
  296. //-----------------------------------------------------------------------
  297. // function : push_front
  298. /// @brief Insert a move of the elements of the deque V1 in the front
  299. /// of the container
  300. /// @param [in] V1 : deque with the elements to insert
  301. /// @return reference to the deque after the insertion
  302. //-----------------------------------------------------------------------
  303. deque_cnc & push_front(std::deque<value_type, Allocator> && V1)
  304. {
  305. std::lock_guard < spinlock_t > S(spl);
  306. for (size_type i = 0; i < V1.size(); ++i)
  307. dq.emplace_front(std::move(V1[i]));
  308. return *this;
  309. };
  310. //
  311. //-----------------------------------------------------------------------
  312. // function :pop_front
  313. /// @brief erase the first element of the container
  314. //-----------------------------------------------------------------------
  315. void pop_front(void)
  316. {
  317. std::lock_guard < spinlock_t > S(spl);
  318. dq.pop_front();
  319. };
  320. //
  321. //-----------------------------------------------------------------------
  322. // function :pop_copy_front
  323. /// @brief erase the first element of the tree and return a copy over P
  324. /// @param [out] P : reference to a variable where copy the element
  325. /// @return code of the operation
  326. /// true- Element erased
  327. /// false - Empty tree
  328. //-----------------------------------------------------------------------
  329. bool pop_copy_front(value_type & P)
  330. { //-------------------------- begin -----------------------------
  331. std::lock_guard < spinlock_t > S(spl);
  332. if (dq.size() == 0) return false;
  333. P = dq.front();
  334. dq.pop_front();
  335. return true;
  336. };
  337. //
  338. //------------------------------------------------------------------------
  339. // function :pop_move_front
  340. /// @brief erase the first element of the tree and return a move over P
  341. /// @param [out] P : reference to a variable where move the element
  342. /// @return code of the operation
  343. /// true- Element erased
  344. /// false - Empty tree
  345. //------------------------------------------------------------------------
  346. bool pop_move_front(value_type & P)
  347. { //-------------------------- begin -----------------------------
  348. std::lock_guard < spinlock_t > S(spl);
  349. if (dq.size() == 0) return false;
  350. P = std::move(dq.front());
  351. dq.pop_front();
  352. return true;
  353. };
  354. };
  355. // end class deque_cnc
  356. //***************************************************************************
  357. };// end namespace common
  358. };// end namespace sort
  359. };// end namespace boost
  360. //***************************************************************************
  361. #endif