|
||||
File indexing completed on 2025-01-18 09:51:46
0001 //---------------------------------------------------------------------------- 0002 /// @file circular_buffer.hpp 0003 /// @brief This file contains the implementation of the circular buffer 0004 /// 0005 /// @author Copyright (c) 2010 2015 Francisco José Tapia (fjtapia@gmail.com )\n 0006 /// Distributed under the Boost Software License, Version 1.0.\n 0007 /// ( See accompanyingfile LICENSE_1_0.txt or copy at 0008 /// http://www.boost.org/LICENSE_1_0.txt ) 0009 /// @version 0.1 0010 /// 0011 /// @remarks 0012 //----------------------------------------------------------------------------- 0013 #ifndef __BOOST_SORT_COMMON_UTIL_CIRCULAR_BUFFER_HPP 0014 #define __BOOST_SORT_COMMON_UTIL_CIRCULAR_BUFFER_HPP 0015 0016 #include <ciso646> 0017 #include <memory> 0018 #include <cassert> 0019 #include <exception> 0020 #include <boost/sort/common/util/algorithm.hpp> 0021 #include <boost/sort/common/util/traits.hpp> 0022 0023 namespace boost 0024 { 0025 namespace sort 0026 { 0027 namespace common 0028 { 0029 namespace util 0030 { 0031 0032 //--------------------------------------------------------------------------- 0033 /// @class circular_buffer 0034 /// @brief This class implement a circular buffer 0035 /// @remarks 0036 //--------------------------------------------------------------------------- 0037 template <class Value_t, uint32_t Power2 = 11> 0038 struct circular_buffer 0039 { 0040 //------------------------------------------------------------------------ 0041 // STATIC CHECK 0042 //------------------------------------------------------------------------ 0043 static_assert ( Power2 != 0, "Wrong Power2"); 0044 0045 //------------------------------------------------------------------------ 0046 // DEFINITIONS 0047 //------------------------------------------------------------------------ 0048 typedef Value_t value_t; 0049 0050 //------------------------------------------------------------------------ 0051 // VARIABLES 0052 //------------------------------------------------------------------------ 0053 const size_t NMAX = (size_t) 1 << Power2; 0054 const size_t MASK = (NMAX - 1); 0055 const size_t BLOCK_SIZE = NMAX >> 1; 0056 const size_t LOG_BLOCK = Power2 - 1; 0057 Value_t * ptr = nullptr; 0058 0059 //------------------------------------------------------------------------ 0060 // first and last are the position of the first and last elements 0061 // always are in the range [0, NMAX - 1] 0062 //------------------------------------------------------------------------ 0063 size_t nelem, first_pos; 0064 bool initialized; 0065 0066 // 0067 //------------------------------------------------------------------------ 0068 // function : circular_buffer 0069 /// @brief constructor of the class 0070 //----------------------------------------------------------------------- 0071 circular_buffer(void) 0072 : ptr(nullptr), nelem(0), first_pos(0), initialized(false) 0073 { 0074 ptr = static_cast <Value_t*> (std::malloc (NMAX * sizeof(Value_t))); 0075 if (ptr == nullptr) throw std::bad_alloc(); 0076 }; 0077 // 0078 //------------------------------------------------------------------------ 0079 // function : ~circular_buffer 0080 /// @brief destructor of the class 0081 //----------------------------------------------------------------------- 0082 ~circular_buffer() 0083 { 0084 if (initialized) 0085 { for (size_t i = 0; i < NMAX; ++i) (ptr + i)->~Value_t(); 0086 initialized = false; 0087 }; 0088 std::free(static_cast <void*> (ptr)); 0089 } 0090 ; 0091 // 0092 //------------------------------------------------------------------------ 0093 // function : initialize 0094 /// @brief : initialize the memory of the buffer from the uninitialize 0095 // memory obtained from the temporary buffer 0096 /// @param val : value used to initialize the memory 0097 //----------------------------------------------------------------------- 0098 void initialize(Value_t & val) 0099 { 0100 assert (initialized == false); 0101 ::new (static_cast<void*>(ptr)) Value_t(std::move(val)); 0102 for (size_t i = 1; i < NMAX; ++i) 0103 ::new (static_cast<void*>(ptr + i)) Value_t(std::move(ptr[i - 1])); 0104 val = std::move(ptr[NMAX - 1]); 0105 initialized = true; 0106 }; 0107 // 0108 //------------------------------------------------------------------------ 0109 // function : destroy_all 0110 /// @brief : destroy all the objects in the internal memory 0111 //----------------------------------------------------------------------- 0112 void destroy_all(void) { destroy(ptr, ptr + NMAX); }; 0113 // 0114 //------------------------------------------------------------------------ 0115 // function : get_buffer 0116 /// @brief return the internal memory of the circular buffer 0117 /// @return pointer to the internal memory of the buffer 0118 //----------------------------------------------------------------------- 0119 Value_t * get_buffer(void) { return ptr; }; 0120 // 0121 //------------------------------------------------------------------------ 0122 // function : empty 0123 /// @brief return if the buffer is empty 0124 /// @return true : empty 0125 //----------------------------------------------------------------------- 0126 bool empty(void) const {return (nelem == 0); }; 0127 // 0128 //------------------------------------------------------------------------ 0129 // function : full 0130 /// @brief return if the buffer is full 0131 /// @return true : full 0132 //----------------------------------------------------------------------- 0133 bool full(void) const { return (nelem == NMAX); }; 0134 // 0135 //------------------------------------------------------------------------ 0136 // function : size 0137 /// @brief return the number of elements stored in the buffer 0138 /// @return number of elements stored 0139 //----------------------------------------------------------------------- 0140 size_t size(void) const { return nelem;}; 0141 // 0142 //------------------------------------------------------------------------ 0143 // function : capacity 0144 /// @brief : return the maximun capacity of the buffer 0145 /// @return number of elements 0146 //----------------------------------------------------------------------- 0147 size_t capacity(void) const { return NMAX;}; 0148 // 0149 //------------------------------------------------------------------------ 0150 // function : free_size 0151 /// @brief return the free positions in the buffer 0152 /// @return number of elements 0153 //----------------------------------------------------------------------- 0154 size_t free_size(void) const { return (NMAX - nelem); }; 0155 // 0156 //------------------------------------------------------------------------ 0157 // function : clear 0158 /// @brief clear the buffer 0159 //----------------------------------------------------------------------- 0160 void clear(void) { nelem = first_pos = 0; }; 0161 // 0162 //------------------------------------------------------------------------ 0163 // function : front 0164 /// @brief return the first element of the buffer 0165 /// @return reference to the first value 0166 //----------------------------------------------------------------------- 0167 Value_t & front(void) 0168 { 0169 #ifdef __BS_DEBUG 0170 assert (nelem > 0); 0171 #endif 0172 return (ptr[first_pos]); 0173 }; 0174 // 0175 //------------------------------------------------------------------------ 0176 // function :front 0177 /// @brief return the first element of the buffer 0178 /// @return const reference to the first value 0179 //----------------------------------------------------------------------- 0180 const Value_t & front(void) const 0181 { 0182 #ifdef __BS_DEBUG 0183 assert ( nelem > 0 ); 0184 #endif 0185 return (ptr[first_pos]); 0186 }; 0187 // 0188 //------------------------------------------------------------------------ 0189 // function : back 0190 /// @brief reference to the last value of the buffer 0191 /// @return reference to the last value 0192 //----------------------------------------------------------------------- 0193 Value_t & back(void) 0194 { 0195 #ifdef __BS_DEBUG 0196 assert ( nelem > 0 ); 0197 #endif 0198 return (ptr[(first_pos + nelem - 1) & MASK]); 0199 }; 0200 // 0201 //------------------------------------------------------------------------ 0202 // function : back 0203 /// @brief reference to the last value of the buffer 0204 /// @return const reference to the last value 0205 //----------------------------------------------------------------------- 0206 const Value_t & back(void) const 0207 { 0208 #ifdef __BS_DEBUG 0209 assert ( nelem > 0 ); 0210 #endif 0211 return (ptr[(first_pos + nelem - 1) & MASK]); 0212 }; 0213 // 0214 //------------------------------------------------------------------------ 0215 // function : operator [] 0216 /// @brief positional access to the elements 0217 /// @param pos rquested 0218 /// @return reference to the element 0219 //----------------------------------------------------------------------- 0220 Value_t & operator[](uint32_t pos) 0221 { 0222 #ifdef __BS_DEBUG 0223 assert ( nelem > 0 ); 0224 #endif 0225 return ptr[(first_pos + pos) & MASK]; 0226 }; 0227 // 0228 //------------------------------------------------------------------------ 0229 // function : operator [] 0230 /// @brief positional access to the elements 0231 /// @param pos rquested 0232 /// @return const reference to the element 0233 //----------------------------------------------------------------------- 0234 const Value_t & operator[](uint32_t pos) const 0235 { 0236 0237 #ifdef __BS_DEBUG 0238 assert ( nelem > 0 ); 0239 #endif 0240 return ptr[(first_pos + pos) & MASK]; 0241 }; 0242 // 0243 //------------------------------------------------------------------------ 0244 // function : push_front 0245 /// @brief insert an element in the first position of the buffer 0246 /// @param val : const value to insert 0247 //----------------------------------------------------------------------- 0248 void push_front(const Value_t & val) 0249 { 0250 #ifdef __BS_DEBUG 0251 assert ( nelem != NMAX); 0252 #endif 0253 ++nelem; 0254 first_pos = ((first_pos + MASK) & MASK); 0255 ptr[first_pos] = val; 0256 0257 }; 0258 // 0259 //------------------------------------------------------------------------ 0260 // function : push_front 0261 /// @brief insert an element in the first position of the buffer 0262 /// @param val : rvalue to insert 0263 //----------------------------------------------------------------------- 0264 void push_front(Value_t && val) 0265 { 0266 #ifdef __BS_DEBUG 0267 assert ( nelem != NMAX); 0268 #endif 0269 ++nelem; 0270 first_pos = ((first_pos + MASK) & MASK); 0271 ptr[first_pos] = val; 0272 }; 0273 // 0274 //------------------------------------------------------------------------ 0275 // function : push_back 0276 /// @brief insert an element in the last position of the buffer 0277 /// @param val : value to insert 0278 //----------------------------------------------------------------------- 0279 void push_back(const Value_t & val) 0280 { 0281 #ifdef __BS_DEBUG 0282 assert ( nelem != NMAX); 0283 #endif 0284 ptr[(first_pos + (nelem++)) & MASK] = val; 0285 }; 0286 // 0287 //------------------------------------------------------------------------ 0288 // function : push_back 0289 /// @brief insert an element in the last position of the buffer 0290 /// @param val : value to insert 0291 //----------------------------------------------------------------------- 0292 void push_back(Value_t && val) 0293 { 0294 #ifdef __BS_DEBUG 0295 assert ( nelem != NMAX); 0296 #endif 0297 ptr[(first_pos + (nelem++)) & MASK] = std::move(val); 0298 }; 0299 // 0300 //------------------------------------------------------------------------ 0301 // function : pop_front 0302 /// @brief remove the first element of the buffer 0303 //----------------------------------------------------------------------- 0304 void pop_front(void) 0305 { 0306 #ifdef __BS_DEBUG 0307 assert ( nelem > 0 ); 0308 #endif 0309 --nelem; 0310 (++first_pos) &= MASK; 0311 }; 0312 // 0313 //------------------------------------------------------------------------ 0314 // function : pop_back 0315 /// @brief remove the last element of the buffer 0316 //----------------------------------------------------------------------- 0317 void pop_back(void) 0318 { 0319 #ifdef __BS_DEBUG 0320 assert ( nelem > 0 ); 0321 #endif 0322 --nelem; 0323 }; 0324 0325 template<class iter_t> 0326 void pop_copy_front(iter_t it_dest, size_t num); 0327 0328 template<class iter_t> 0329 void pop_move_front(iter_t it_dest, size_t num); 0330 0331 template<class iter_t> 0332 void pop_copy_back(iter_t it_dest, size_t num); 0333 0334 template<class iter_t> 0335 void pop_move_back(iter_t it_dest, size_t num); 0336 0337 template<class iter_t> 0338 void push_copy_front(iter_t it_src, size_t num); 0339 0340 template<class iter_t> 0341 void push_move_front(iter_t it_src, size_t num); 0342 0343 template<class iter_t> 0344 void push_copy_back(iter_t it_src, size_t num); 0345 0346 template<class iter_t> 0347 void push_move_back(iter_t it_src, size_t num); 0348 0349 //--------------------------------------------------------------------------- 0350 };// End of class circular_buffer 0351 //--------------------------------------------------------------------------- 0352 // 0353 // 0354 //############################################################################ 0355 // ## 0356 // N O N I N L I N E F U N C T I O N S ## 0357 // ## 0358 //############################################################################ 0359 // 0360 //------------------------------------------------------------------------ 0361 // function : pop_copy_front 0362 /// @brief copy and delete num elements from the front of the buffer 0363 /// @param it_dest : iterator to the first position where copy the elements 0364 /// @param num : number of elements to copy 0365 //----------------------------------------------------------------------- 0366 template <class Value_t, uint32_t Power2> 0367 template<class iter_t> 0368 void circular_buffer<Value_t, Power2> 0369 ::pop_copy_front(iter_t it_dest, size_t num) 0370 { 0371 static_assert ( std::is_same <value_iter<iter_t>, Value_t>::value, 0372 "Incompatible iterator"); 0373 if (num == 0) return; 0374 #ifdef __BS_DEBUG 0375 assert ( num <= nelem); 0376 #endif 0377 nelem -= num; 0378 size_t pos = first_pos; 0379 first_pos = (first_pos + num) & MASK; 0380 for (size_t i = 0; i < num; ++i) 0381 { 0382 *(it_dest++) = ptr[pos++ & MASK]; 0383 }; 0384 first_pos &= MASK; 0385 }; 0386 // 0387 //------------------------------------------------------------------------ 0388 // function : pop_move_front 0389 /// @brief move num elements from the front of the buffer to the place 0390 // pointed by it_dest 0391 /// @param it_dest : iterator to the first position where move the elements 0392 /// @param num : number of elements to move 0393 //----------------------------------------------------------------------- 0394 template <class Value_t, uint32_t Power2> 0395 template<class iter_t> 0396 void circular_buffer<Value_t, Power2> 0397 :: pop_move_front(iter_t it_dest, size_t num) 0398 { 0399 static_assert ( std::is_same <value_iter<iter_t>, Value_t>::value, 0400 "Incompatible iterator"); 0401 if (num == 0) return; 0402 #ifdef __BS_DEBUG 0403 assert ( num <= nelem); 0404 #endif 0405 nelem -= num; 0406 size_t pos = first_pos; 0407 first_pos = (first_pos + num) & MASK; 0408 for (size_t i = 0; i < num; ++i) 0409 { 0410 *(it_dest++) = std::move(ptr[pos++ & MASK]); 0411 }; 0412 first_pos &= MASK; 0413 }; 0414 // 0415 //------------------------------------------------------------------------ 0416 // function : pop_copy_back 0417 /// @brief copy and delete num elements from the back of the buffer 0418 /// @param p1 : iterator where begin to copy the elements 0419 /// @param num : number of elements to copy 0420 //----------------------------------------------------------------------- 0421 template <class Value_t, uint32_t Power2> 0422 template<class iter_t> 0423 void circular_buffer<Value_t, Power2> 0424 ::pop_copy_back(iter_t it_dest, size_t num) 0425 { 0426 static_assert ( std::is_same <value_iter<iter_t>, Value_t>::value, 0427 "Incompatible iterator"); 0428 if (num == 0) return; 0429 #ifdef __BS_DEBUG 0430 assert ( num <= nelem); 0431 #endif 0432 nelem -= num; 0433 size_t pos = (first_pos + nelem) & MASK; 0434 for (size_t i = 0; i < num; ++i) 0435 { 0436 *(it_dest++) = ptr[pos++ & MASK]; 0437 }; 0438 }; 0439 // 0440 //------------------------------------------------------------------------ 0441 // function : pop_move_back 0442 /// @brief move and delete num elements from the back of the buffer 0443 /// @param p1 : iterator where begin to move the elements 0444 /// @param num : number of elements to move 0445 //----------------------------------------------------------------------- 0446 template <class Value_t, uint32_t Power2> 0447 template<class iter_t> 0448 void circular_buffer<Value_t, Power2> 0449 ::pop_move_back(iter_t it_dest, size_t num) 0450 { 0451 static_assert ( std::is_same <value_iter<iter_t>, Value_t>::value, 0452 "Incompatible iterator"); 0453 if (num == 0) return; 0454 #ifdef __BS_DEBUG 0455 assert ( num <= nelem); 0456 #endif 0457 nelem -= num; 0458 size_t pos = (first_pos + nelem) & MASK; 0459 for (size_t i = 0; i < num; ++i) 0460 { 0461 *(it_dest++) = std::move(ptr[pos++ & MASK]); 0462 }; 0463 }; 0464 // 0465 //------------------------------------------------------------------------ 0466 // function : push_copy_front 0467 /// @brief copy num elements in the front of the buffer 0468 /// @param it_src : iterator from where begin to copy the elements 0469 /// @param mun : number of element to copy 0470 //----------------------------------------------------------------------- 0471 template <class Value_t, uint32_t Power2> 0472 template<class iter_t> 0473 void circular_buffer<Value_t, Power2> 0474 ::push_copy_front(iter_t it_src, size_t num) 0475 { 0476 static_assert ( std::is_same <value_iter<iter_t>, Value_t>::value, 0477 "Incompatible iterator"); 0478 if (num == 0) return; 0479 #ifdef __BS_DEBUG 0480 assert ( free_size() >= num); 0481 #endif 0482 nelem += num; 0483 0484 first_pos = (first_pos + NMAX - num) & MASK; 0485 size_t pos = first_pos; 0486 for (size_t i = 0; i < num; ++i) 0487 { 0488 ptr[(pos++) & MASK] = *(it_src++); 0489 }; 0490 }; 0491 // 0492 //------------------------------------------------------------------------ 0493 // function : push_move_front 0494 /// @brief move num elements in the front of the buffer 0495 /// @param p1 : iterator from where begin to move the elements 0496 /// @param mun : number of element to move 0497 //----------------------------------------------------------------------- 0498 template <class Value_t, uint32_t Power2> 0499 template<class iter_t> 0500 void circular_buffer<Value_t, Power2> 0501 ::push_move_front(iter_t it_src, size_t num) 0502 { 0503 static_assert ( std::is_same <value_iter<iter_t>, Value_t>::value, 0504 "Incompatible iterator"); 0505 if (num == 0) return; 0506 #ifdef __BS_DEBUG 0507 assert ( free_size() >= num); 0508 #endif 0509 nelem += num; 0510 size_t pos = first_pos; 0511 for (size_t i = 0; i < num; ++i) 0512 { 0513 ptr[(pos++) & MASK] = std::move(*(it_src++)); 0514 }; 0515 }; 0516 // 0517 //------------------------------------------------------------------------ 0518 // function : push_copy_back 0519 /// @brief copy num elements in the back of the buffer 0520 /// @param p1 : iterator from where begin to copy the elements 0521 /// @param mun : number of element to copy 0522 //----------------------------------------------------------------------- 0523 template <class Value_t, uint32_t Power2> 0524 template<class iter_t> 0525 void circular_buffer<Value_t, Power2> 0526 ::push_copy_back(iter_t it_src, size_t num) 0527 { 0528 static_assert ( std::is_same <value_iter<iter_t>, Value_t>::value, 0529 "Incompatible iterator"); 0530 if (num == 0) return; 0531 #ifdef __BS_DEBUG 0532 assert ( free_size() >= num); 0533 #endif 0534 size_t pos = first_pos + nelem; 0535 nelem += num; 0536 for (size_t i = 0; i < num; ++i) 0537 { 0538 ptr[(pos++) & MASK] = *(it_src++); 0539 }; 0540 }; 0541 // 0542 //------------------------------------------------------------------------ 0543 // function : push_move_back 0544 /// @brief move num elements in the back of the buffer 0545 /// @param p1 : iterator from where begin to move the elements 0546 /// @param mun : number of element to move 0547 //----------------------------------------------------------------------- 0548 template <class Value_t, uint32_t Power2> 0549 template<class iter_t> 0550 void circular_buffer<Value_t, Power2> 0551 ::push_move_back(iter_t it_src, size_t num) 0552 { 0553 static_assert ( std::is_same <value_iter<iter_t>, Value_t>::value, 0554 "Incompatible iterator"); 0555 if (num == 0) return; 0556 #ifdef __BS_DEBUG 0557 assert ( free_size() >= num); 0558 #endif 0559 size_t pos = first_pos + nelem; 0560 nelem += num; 0561 for (size_t i = 0; i < num; ++i) 0562 { 0563 ptr[(pos++) & MASK] = std::move(*(it_src++)); 0564 }; 0565 }; 0566 0567 //**************************************************************************** 0568 };// End namespace util 0569 };// End namespace common 0570 };// End namespace sort 0571 };// End namespace boost 0572 //**************************************************************************** 0573 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |