spsc_queue.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. // lock-free single-producer/single-consumer ringbuffer
  2. // this algorithm is implemented in various projects (linux kernel)
  3. //
  4. // Copyright (C) 2009-2013 Tim Blechmann
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #ifndef BOOST_LOCKFREE_SPSC_QUEUE_HPP_INCLUDED
  10. #define BOOST_LOCKFREE_SPSC_QUEUE_HPP_INCLUDED
  11. #include <algorithm>
  12. #include <memory>
  13. #include <boost/aligned_storage.hpp>
  14. #include <boost/assert.hpp>
  15. #ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
  16. #include <boost/noncopyable.hpp>
  17. #endif
  18. #include <boost/static_assert.hpp>
  19. #include <boost/utility.hpp>
  20. #include <boost/type_traits/has_trivial_destructor.hpp>
  21. #include <boost/lockfree/detail/atomic.hpp>
  22. #include <boost/lockfree/detail/branch_hints.hpp>
  23. #include <boost/lockfree/detail/parameter.hpp>
  24. #include <boost/lockfree/detail/prefix.hpp>
  25. namespace boost {
  26. namespace lockfree {
  27. namespace detail {
  28. typedef parameter::parameters<boost::parameter::optional<tag::capacity>,
  29. boost::parameter::optional<tag::allocator>
  30. > ringbuffer_signature;
  31. template <typename T>
  32. class ringbuffer_base
  33. #ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
  34. : boost::noncopyable
  35. #endif
  36. {
  37. #ifndef BOOST_DOXYGEN_INVOKED
  38. typedef std::size_t size_t;
  39. static const int padding_size = BOOST_LOCKFREE_CACHELINE_BYTES - sizeof(size_t);
  40. atomic<size_t> write_index_;
  41. char padding1[padding_size]; /* force read_index and write_index to different cache lines */
  42. atomic<size_t> read_index_;
  43. #ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
  44. ringbuffer_base(ringbuffer_base const &) = delete;
  45. ringbuffer_base(ringbuffer_base &&) = delete;
  46. const ringbuffer_base& operator=( const ringbuffer_base& ) = delete;
  47. #endif
  48. protected:
  49. ringbuffer_base(void):
  50. write_index_(0), read_index_(0)
  51. {}
  52. static size_t next_index(size_t arg, size_t max_size)
  53. {
  54. size_t ret = arg + 1;
  55. while (unlikely(ret >= max_size))
  56. ret -= max_size;
  57. return ret;
  58. }
  59. static size_t read_available(size_t write_index, size_t read_index, size_t max_size)
  60. {
  61. if (write_index >= read_index)
  62. return write_index - read_index;
  63. size_t ret = write_index + max_size - read_index;
  64. return ret;
  65. }
  66. static size_t write_available(size_t write_index, size_t read_index, size_t max_size)
  67. {
  68. size_t ret = read_index - write_index - 1;
  69. if (write_index >= read_index)
  70. ret += max_size;
  71. return ret;
  72. }
  73. bool push(T const & t, T * buffer, size_t max_size)
  74. {
  75. const size_t write_index = write_index_.load(memory_order_relaxed); // only written from push thread
  76. const size_t next = next_index(write_index, max_size);
  77. if (next == read_index_.load(memory_order_acquire))
  78. return false; /* ringbuffer is full */
  79. new (buffer + write_index) T(t); // copy-construct
  80. write_index_.store(next, memory_order_release);
  81. return true;
  82. }
  83. size_t push(const T * input_buffer, size_t input_count, T * internal_buffer, size_t max_size)
  84. {
  85. return push(input_buffer, input_buffer + input_count, internal_buffer, max_size) - input_buffer;
  86. }
  87. template <typename ConstIterator>
  88. ConstIterator push(ConstIterator begin, ConstIterator end, T * internal_buffer, size_t max_size)
  89. {
  90. // FIXME: avoid std::distance
  91. const size_t write_index = write_index_.load(memory_order_relaxed); // only written from push thread
  92. const size_t read_index = read_index_.load(memory_order_acquire);
  93. const size_t avail = write_available(write_index, read_index, max_size);
  94. if (avail == 0)
  95. return begin;
  96. size_t input_count = std::distance(begin, end);
  97. input_count = (std::min)(input_count, avail);
  98. size_t new_write_index = write_index + input_count;
  99. const ConstIterator last = boost::next(begin, input_count);
  100. if (write_index + input_count > max_size) {
  101. /* copy data in two sections */
  102. const size_t count0 = max_size - write_index;
  103. const ConstIterator midpoint = boost::next(begin, count0);
  104. std::uninitialized_copy(begin, midpoint, internal_buffer + write_index);
  105. std::uninitialized_copy(midpoint, last, internal_buffer);
  106. new_write_index -= max_size;
  107. } else {
  108. std::uninitialized_copy(begin, last, internal_buffer + write_index);
  109. if (new_write_index == max_size)
  110. new_write_index = 0;
  111. }
  112. write_index_.store(new_write_index, memory_order_release);
  113. return last;
  114. }
  115. bool pop (T & ret, T * buffer, size_t max_size)
  116. {
  117. const size_t write_index = write_index_.load(memory_order_acquire);
  118. const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
  119. if (empty(write_index, read_index))
  120. return false;
  121. ret = buffer[read_index];
  122. buffer[read_index].~T();
  123. size_t next = next_index(read_index, max_size);
  124. read_index_.store(next, memory_order_release);
  125. return true;
  126. }
  127. size_t pop (T * output_buffer, size_t output_count, T * internal_buffer, size_t max_size)
  128. {
  129. const size_t write_index = write_index_.load(memory_order_acquire);
  130. const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
  131. const size_t avail = read_available(write_index, read_index, max_size);
  132. if (avail == 0)
  133. return 0;
  134. output_count = (std::min)(output_count, avail);
  135. size_t new_read_index = read_index + output_count;
  136. if (read_index + output_count > max_size) {
  137. /* copy data in two sections */
  138. const size_t count0 = max_size - read_index;
  139. const size_t count1 = output_count - count0;
  140. copy_and_delete(internal_buffer + read_index, internal_buffer + max_size, output_buffer);
  141. copy_and_delete(internal_buffer, internal_buffer + count1, output_buffer + count0);
  142. new_read_index -= max_size;
  143. } else {
  144. copy_and_delete(internal_buffer + read_index, internal_buffer + read_index + output_count, output_buffer);
  145. if (new_read_index == max_size)
  146. new_read_index = 0;
  147. }
  148. read_index_.store(new_read_index, memory_order_release);
  149. return output_count;
  150. }
  151. template <typename OutputIterator>
  152. size_t pop (OutputIterator it, T * internal_buffer, size_t max_size)
  153. {
  154. const size_t write_index = write_index_.load(memory_order_acquire);
  155. const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
  156. const size_t avail = read_available(write_index, read_index, max_size);
  157. if (avail == 0)
  158. return 0;
  159. size_t new_read_index = read_index + avail;
  160. if (read_index + avail > max_size) {
  161. /* copy data in two sections */
  162. const size_t count0 = max_size - read_index;
  163. const size_t count1 = avail - count0;
  164. it = copy_and_delete(internal_buffer + read_index, internal_buffer + max_size, it);
  165. copy_and_delete(internal_buffer, internal_buffer + count1, it);
  166. new_read_index -= max_size;
  167. } else {
  168. copy_and_delete(internal_buffer + read_index, internal_buffer + read_index + avail, it);
  169. if (new_read_index == max_size)
  170. new_read_index = 0;
  171. }
  172. read_index_.store(new_read_index, memory_order_release);
  173. return avail;
  174. }
  175. #endif
  176. public:
  177. /** reset the ringbuffer
  178. *
  179. * \note Not thread-safe
  180. * */
  181. void reset(void)
  182. {
  183. write_index_.store(0, memory_order_relaxed);
  184. read_index_.store(0, memory_order_release);
  185. }
  186. /** Check if the ringbuffer is empty
  187. *
  188. * \return true, if the ringbuffer is empty, false otherwise
  189. * \note Due to the concurrent nature of the ringbuffer the result may be inaccurate.
  190. * */
  191. bool empty(void)
  192. {
  193. return empty(write_index_.load(memory_order_relaxed), read_index_.load(memory_order_relaxed));
  194. }
  195. /**
  196. * \return true, if implementation is lock-free.
  197. *
  198. * */
  199. bool is_lock_free(void) const
  200. {
  201. return write_index_.is_lock_free() && read_index_.is_lock_free();
  202. }
  203. private:
  204. bool empty(size_t write_index, size_t read_index)
  205. {
  206. return write_index == read_index;
  207. }
  208. template< class OutputIterator >
  209. OutputIterator copy_and_delete( T * first, T * last, OutputIterator out )
  210. {
  211. if (boost::has_trivial_destructor<T>::value) {
  212. return std::copy(first, last, out); // will use memcpy if possible
  213. } else {
  214. for (; first != last; ++first, ++out) {
  215. *out = *first;
  216. first->~T();
  217. }
  218. return out;
  219. }
  220. }
  221. };
  222. template <typename T, std::size_t MaxSize>
  223. class compile_time_sized_ringbuffer:
  224. public ringbuffer_base<T>
  225. {
  226. typedef std::size_t size_type;
  227. static const std::size_t max_size = MaxSize + 1;
  228. typedef typename boost::aligned_storage<max_size * sizeof(T),
  229. boost::alignment_of<T>::value
  230. >::type storage_type;
  231. storage_type storage_;
  232. T * data()
  233. {
  234. return static_cast<T*>(storage_.address());
  235. }
  236. public:
  237. bool push(T const & t)
  238. {
  239. return ringbuffer_base<T>::push(t, data(), max_size);
  240. }
  241. bool pop(T & ret)
  242. {
  243. return ringbuffer_base<T>::pop(ret, data(), max_size);
  244. }
  245. size_type push(T const * t, size_type size)
  246. {
  247. return ringbuffer_base<T>::push(t, size, data(), max_size);
  248. }
  249. template <size_type size>
  250. size_type push(T const (&t)[size])
  251. {
  252. return push(t, size);
  253. }
  254. template <typename ConstIterator>
  255. ConstIterator push(ConstIterator begin, ConstIterator end)
  256. {
  257. return ringbuffer_base<T>::push(begin, end, data(), max_size);
  258. }
  259. size_type pop(T * ret, size_type size)
  260. {
  261. return ringbuffer_base<T>::pop(ret, size, data(), max_size);
  262. }
  263. template <size_type size>
  264. size_type pop(T (&ret)[size])
  265. {
  266. return pop(ret, size);
  267. }
  268. template <typename OutputIterator>
  269. size_type pop(OutputIterator it)
  270. {
  271. return ringbuffer_base<T>::pop(it, data(), max_size);
  272. }
  273. };
  274. template <typename T, typename Alloc>
  275. class runtime_sized_ringbuffer:
  276. public ringbuffer_base<T>,
  277. private Alloc
  278. {
  279. typedef std::size_t size_type;
  280. size_type max_elements_;
  281. typedef typename Alloc::pointer pointer;
  282. pointer array_;
  283. public:
  284. explicit runtime_sized_ringbuffer(size_type max_elements):
  285. max_elements_(max_elements + 1)
  286. {
  287. array_ = Alloc::allocate(max_elements_);
  288. }
  289. template <typename U>
  290. runtime_sized_ringbuffer(typename Alloc::template rebind<U>::other const & alloc, size_type max_elements):
  291. Alloc(alloc), max_elements_(max_elements + 1)
  292. {
  293. array_ = Alloc::allocate(max_elements_);
  294. }
  295. runtime_sized_ringbuffer(Alloc const & alloc, size_type max_elements):
  296. Alloc(alloc), max_elements_(max_elements + 1)
  297. {
  298. array_ = Alloc::allocate(max_elements_);
  299. }
  300. ~runtime_sized_ringbuffer(void)
  301. {
  302. // destroy all remaining items
  303. T out;
  304. while (pop(out)) {};
  305. Alloc::deallocate(array_, max_elements_);
  306. }
  307. bool push(T const & t)
  308. {
  309. return ringbuffer_base<T>::push(t, &*array_, max_elements_);
  310. }
  311. bool pop(T & ret)
  312. {
  313. return ringbuffer_base<T>::pop(ret, &*array_, max_elements_);
  314. }
  315. size_type push(T const * t, size_type size)
  316. {
  317. return ringbuffer_base<T>::push(t, size, &*array_, max_elements_);
  318. }
  319. template <size_type size>
  320. size_type push(T const (&t)[size])
  321. {
  322. return push(t, size);
  323. }
  324. template <typename ConstIterator>
  325. ConstIterator push(ConstIterator begin, ConstIterator end)
  326. {
  327. return ringbuffer_base<T>::push(begin, end, array_, max_elements_);
  328. }
  329. size_type pop(T * ret, size_type size)
  330. {
  331. return ringbuffer_base<T>::pop(ret, size, array_, max_elements_);
  332. }
  333. template <size_type size>
  334. size_type pop(T (&ret)[size])
  335. {
  336. return pop(ret, size);
  337. }
  338. template <typename OutputIterator>
  339. size_type pop(OutputIterator it)
  340. {
  341. return ringbuffer_base<T>::pop(it, array_, max_elements_);
  342. }
  343. };
  344. template <typename T, typename A0, typename A1>
  345. struct make_ringbuffer
  346. {
  347. typedef typename ringbuffer_signature::bind<A0, A1>::type bound_args;
  348. typedef extract_capacity<bound_args> extract_capacity_t;
  349. static const bool runtime_sized = !extract_capacity_t::has_capacity;
  350. static const size_t capacity = extract_capacity_t::capacity;
  351. typedef extract_allocator<bound_args, T> extract_allocator_t;
  352. typedef typename extract_allocator_t::type allocator;
  353. // allocator argument is only sane, for run-time sized ringbuffers
  354. BOOST_STATIC_ASSERT((mpl::if_<mpl::bool_<!runtime_sized>,
  355. mpl::bool_<!extract_allocator_t::has_allocator>,
  356. mpl::true_
  357. >::type::value));
  358. typedef typename mpl::if_c<runtime_sized,
  359. runtime_sized_ringbuffer<T, allocator>,
  360. compile_time_sized_ringbuffer<T, capacity>
  361. >::type ringbuffer_type;
  362. };
  363. } /* namespace detail */
  364. /** The spsc_queue class provides a single-writer/single-reader fifo queue, pushing and popping is wait-free.
  365. *
  366. * \b Policies:
  367. * - \c boost::lockfree::capacity<>, optional <br>
  368. * If this template argument is passed to the options, the size of the ringbuffer is set at compile-time.
  369. *
  370. * - \c boost::lockfree::allocator<>, defaults to \c boost::lockfree::allocator<std::allocator<T>> <br>
  371. * Specifies the allocator that is used to allocate the ringbuffer. This option is only valid, if the ringbuffer is configured
  372. * to be sized at run-time
  373. *
  374. * \b Requirements:
  375. * - T must have a default constructor
  376. * - T must be copyable
  377. * */
  378. #ifndef BOOST_DOXYGEN_INVOKED
  379. template <typename T,
  380. class A0 = boost::parameter::void_,
  381. class A1 = boost::parameter::void_>
  382. #else
  383. template <typename T, ...Options>
  384. #endif
  385. class spsc_queue:
  386. public detail::make_ringbuffer<T, A0, A1>::ringbuffer_type
  387. {
  388. private:
  389. #ifndef BOOST_DOXYGEN_INVOKED
  390. typedef typename detail::make_ringbuffer<T, A0, A1>::ringbuffer_type base_type;
  391. static const bool runtime_sized = detail::make_ringbuffer<T, A0, A1>::runtime_sized;
  392. typedef typename detail::make_ringbuffer<T, A0, A1>::allocator allocator_arg;
  393. struct implementation_defined
  394. {
  395. typedef allocator_arg allocator;
  396. typedef std::size_t size_type;
  397. };
  398. #endif
  399. public:
  400. typedef T value_type;
  401. typedef typename implementation_defined::allocator allocator;
  402. typedef typename implementation_defined::size_type size_type;
  403. /** Constructs a spsc_queue
  404. *
  405. * \pre spsc_queue must be configured to be sized at compile-time
  406. */
  407. // @{
  408. spsc_queue(void)
  409. {
  410. BOOST_ASSERT(!runtime_sized);
  411. }
  412. template <typename U>
  413. explicit spsc_queue(typename allocator::template rebind<U>::other const & alloc)
  414. {
  415. // just for API compatibility: we don't actually need an allocator
  416. BOOST_STATIC_ASSERT(!runtime_sized);
  417. }
  418. explicit spsc_queue(allocator const & alloc)
  419. {
  420. // just for API compatibility: we don't actually need an allocator
  421. BOOST_ASSERT(!runtime_sized);
  422. }
  423. // @}
  424. /** Constructs a spsc_queue for element_count elements
  425. *
  426. * \pre spsc_queue must be configured to be sized at run-time
  427. */
  428. // @{
  429. explicit spsc_queue(size_type element_count):
  430. base_type(element_count)
  431. {
  432. BOOST_ASSERT(runtime_sized);
  433. }
  434. template <typename U>
  435. spsc_queue(size_type element_count, typename allocator::template rebind<U>::other const & alloc):
  436. base_type(alloc, element_count)
  437. {
  438. BOOST_STATIC_ASSERT(runtime_sized);
  439. }
  440. spsc_queue(size_type element_count, allocator_arg const & alloc):
  441. base_type(alloc, element_count)
  442. {
  443. BOOST_ASSERT(runtime_sized);
  444. }
  445. // @}
  446. /** Pushes object t to the ringbuffer.
  447. *
  448. * \pre only one thread is allowed to push data to the spsc_queue
  449. * \post object will be pushed to the spsc_queue, unless it is full.
  450. * \return true, if the push operation is successful.
  451. *
  452. * \note Thread-safe and wait-free
  453. * */
  454. bool push(T const & t)
  455. {
  456. return base_type::push(t);
  457. }
  458. /** Pops one object from ringbuffer.
  459. *
  460. * \pre only one thread is allowed to pop data to the spsc_queue
  461. * \post if ringbuffer is not empty, object will be copied to ret.
  462. * \return true, if the pop operation is successful, false if ringbuffer was empty.
  463. *
  464. * \note Thread-safe and wait-free
  465. */
  466. bool pop(T & ret)
  467. {
  468. return base_type::pop(ret);
  469. }
  470. /** Pushes as many objects from the array t as there is space.
  471. *
  472. * \pre only one thread is allowed to push data to the spsc_queue
  473. * \return number of pushed items
  474. *
  475. * \note Thread-safe and wait-free
  476. */
  477. size_type push(T const * t, size_type size)
  478. {
  479. return base_type::push(t, size);
  480. }
  481. /** Pushes as many objects from the array t as there is space available.
  482. *
  483. * \pre only one thread is allowed to push data to the spsc_queue
  484. * \return number of pushed items
  485. *
  486. * \note Thread-safe and wait-free
  487. */
  488. template <size_type size>
  489. size_type push(T const (&t)[size])
  490. {
  491. return push(t, size);
  492. }
  493. /** Pushes as many objects from the range [begin, end) as there is space .
  494. *
  495. * \pre only one thread is allowed to push data to the spsc_queue
  496. * \return iterator to the first element, which has not been pushed
  497. *
  498. * \note Thread-safe and wait-free
  499. */
  500. template <typename ConstIterator>
  501. ConstIterator push(ConstIterator begin, ConstIterator end)
  502. {
  503. return base_type::push(begin, end);
  504. }
  505. /** Pops a maximum of size objects from ringbuffer.
  506. *
  507. * \pre only one thread is allowed to pop data to the spsc_queue
  508. * \return number of popped items
  509. *
  510. * \note Thread-safe and wait-free
  511. * */
  512. size_type pop(T * ret, size_type size)
  513. {
  514. return base_type::pop(ret, size);
  515. }
  516. /** Pops a maximum of size objects from spsc_queue.
  517. *
  518. * \pre only one thread is allowed to pop data to the spsc_queue
  519. * \return number of popped items
  520. *
  521. * \note Thread-safe and wait-free
  522. * */
  523. template <size_type size>
  524. size_type pop(T (&ret)[size])
  525. {
  526. return pop(ret, size);
  527. }
  528. /** Pops objects to the output iterator it
  529. *
  530. * \pre only one thread is allowed to pop data to the spsc_queue
  531. * \return number of popped items
  532. *
  533. * \note Thread-safe and wait-free
  534. * */
  535. template <typename OutputIterator>
  536. size_type pop(OutputIterator it)
  537. {
  538. return base_type::pop(it);
  539. }
  540. /** consumes one element via a functor
  541. *
  542. * pops one element from the queue and applies the functor on this object
  543. *
  544. * \returns true, if one element was consumed
  545. *
  546. * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking
  547. * */
  548. template <typename Functor>
  549. bool consume_one(Functor & f)
  550. {
  551. T element;
  552. bool success = pop(element);
  553. if (success)
  554. f(element);
  555. return success;
  556. }
  557. /// \copydoc boost::lockfree::spsc_queue::consume_one(Functor & rhs)
  558. template <typename Functor>
  559. bool consume_one(Functor const & f)
  560. {
  561. T element;
  562. bool success = pop(element);
  563. if (success)
  564. f(element);
  565. return success;
  566. }
  567. /** consumes all elements via a functor
  568. *
  569. * sequentially pops all elements from the queue and applies the functor on each object
  570. *
  571. * \returns number of elements that are consumed
  572. *
  573. * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking
  574. * */
  575. template <typename Functor>
  576. size_type consume_all(Functor & f)
  577. {
  578. size_type element_count = 0;
  579. while (consume_one(f))
  580. element_count += 1;
  581. return element_count;
  582. }
  583. /// \copydoc boost::lockfree::spsc_queue::consume_all(Functor & rhs)
  584. template <typename Functor>
  585. size_type consume_all(Functor const & f)
  586. {
  587. size_type element_count = 0;
  588. while (consume_one(f))
  589. element_count += 1;
  590. return element_count;
  591. }
  592. };
  593. } /* namespace lockfree */
  594. } /* namespace boost */
  595. #endif /* BOOST_LOCKFREE_SPSC_QUEUE_HPP_INCLUDED */