1 // lock-free single-producer/single-consumer ringbuffer
2 // this algorithm is implemented in various projects (linux kernel)
4 // Copyright (C) 2009-2013 Tim Blechmann
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)
10 #ifndef BOOST_LOCKFREE_SPSC_QUEUE_HPP_INCLUDED
11 #define BOOST_LOCKFREE_SPSC_QUEUE_HPP_INCLUDED
16 #include <boost/aligned_storage.hpp>
17 #include <boost/assert.hpp>
18 #include <boost/static_assert.hpp>
19 #include <boost/utility.hpp>
20 #include <boost/utility/enable_if.hpp>
22 #include <boost/type_traits/has_trivial_destructor.hpp>
23 #include <boost/type_traits/is_convertible.hpp>
25 #include <boost/lockfree/detail/atomic.hpp>
26 #include <boost/lockfree/detail/branch_hints.hpp>
27 #include <boost/lockfree/detail/copy_payload.hpp>
28 #include <boost/lockfree/detail/parameter.hpp>
29 #include <boost/lockfree/detail/prefix.hpp>
31 #ifdef BOOST_HAS_PRAGMA_ONCE
39 typedef parameter::parameters<boost::parameter::optional<tag::capacity>,
40 boost::parameter::optional<tag::allocator>
41 > ringbuffer_signature;
46 #ifndef BOOST_DOXYGEN_INVOKED
47 typedef std::size_t size_t;
48 static const int padding_size = BOOST_LOCKFREE_CACHELINE_BYTES - sizeof(size_t);
49 atomic<size_t> write_index_;
50 char padding1[padding_size]; /* force read_index and write_index to different cache lines */
51 atomic<size_t> read_index_;
53 BOOST_DELETED_FUNCTION(ringbuffer_base(ringbuffer_base const&))
54 BOOST_DELETED_FUNCTION(ringbuffer_base& operator= (ringbuffer_base const&))
57 ringbuffer_base(void):
58 write_index_(0), read_index_(0)
61 static size_t next_index(size_t arg, size_t max_size)
64 while (unlikely(ret >= max_size))
69 static size_t read_available(size_t write_index, size_t read_index, size_t max_size)
71 if (write_index >= read_index)
72 return write_index - read_index;
74 const size_t ret = write_index + max_size - read_index;
78 static size_t write_available(size_t write_index, size_t read_index, size_t max_size)
80 size_t ret = read_index - write_index - 1;
81 if (write_index >= read_index)
86 size_t read_available(size_t max_size) const
88 size_t write_index = write_index_.load(memory_order_relaxed);
89 const size_t read_index = read_index_.load(memory_order_relaxed);
90 return read_available(write_index, read_index, max_size);
93 size_t write_available(size_t max_size) const
95 size_t write_index = write_index_.load(memory_order_relaxed);
96 const size_t read_index = read_index_.load(memory_order_relaxed);
97 return write_available(write_index, read_index, max_size);
100 bool push(T const & t, T * buffer, size_t max_size)
102 const size_t write_index = write_index_.load(memory_order_relaxed); // only written from push thread
103 const size_t next = next_index(write_index, max_size);
105 if (next == read_index_.load(memory_order_acquire))
106 return false; /* ringbuffer is full */
108 new (buffer + write_index) T(t); // copy-construct
110 write_index_.store(next, memory_order_release);
115 size_t push(const T * input_buffer, size_t input_count, T * internal_buffer, size_t max_size)
117 return push(input_buffer, input_buffer + input_count, internal_buffer, max_size) - input_buffer;
120 template <typename ConstIterator>
121 ConstIterator push(ConstIterator begin, ConstIterator end, T * internal_buffer, size_t max_size)
123 // FIXME: avoid std::distance
125 const size_t write_index = write_index_.load(memory_order_relaxed); // only written from push thread
126 const size_t read_index = read_index_.load(memory_order_acquire);
127 const size_t avail = write_available(write_index, read_index, max_size);
132 size_t input_count = std::distance(begin, end);
133 input_count = (std::min)(input_count, avail);
135 size_t new_write_index = write_index + input_count;
137 const ConstIterator last = boost::next(begin, input_count);
139 if (write_index + input_count > max_size) {
140 /* copy data in two sections */
141 const size_t count0 = max_size - write_index;
142 const ConstIterator midpoint = boost::next(begin, count0);
144 std::uninitialized_copy(begin, midpoint, internal_buffer + write_index);
145 std::uninitialized_copy(midpoint, last, internal_buffer);
146 new_write_index -= max_size;
148 std::uninitialized_copy(begin, last, internal_buffer + write_index);
150 if (new_write_index == max_size)
154 write_index_.store(new_write_index, memory_order_release);
158 template <typename Functor>
159 bool consume_one(Functor & functor, T * buffer, size_t max_size)
161 const size_t write_index = write_index_.load(memory_order_acquire);
162 const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
163 if ( empty(write_index, read_index) )
166 T & object_to_consume = buffer[read_index];
167 functor( object_to_consume );
168 object_to_consume.~T();
170 size_t next = next_index(read_index, max_size);
171 read_index_.store(next, memory_order_release);
175 template <typename Functor>
176 bool consume_one(Functor const & functor, T * buffer, size_t max_size)
178 const size_t write_index = write_index_.load(memory_order_acquire);
179 const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
180 if ( empty(write_index, read_index) )
183 T & object_to_consume = buffer[read_index];
184 functor( object_to_consume );
185 object_to_consume.~T();
187 size_t next = next_index(read_index, max_size);
188 read_index_.store(next, memory_order_release);
192 template <typename Functor>
193 size_t consume_all (Functor const & functor, T * internal_buffer, size_t max_size)
195 const size_t write_index = write_index_.load(memory_order_acquire);
196 const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
198 const size_t avail = read_available(write_index, read_index, max_size);
203 const size_t output_count = avail;
205 size_t new_read_index = read_index + output_count;
207 if (read_index + output_count > max_size) {
208 /* copy data in two sections */
209 const size_t count0 = max_size - read_index;
210 const size_t count1 = output_count - count0;
212 run_functor_and_delete(internal_buffer + read_index, internal_buffer + max_size, functor);
213 run_functor_and_delete(internal_buffer, internal_buffer + count1, functor);
215 new_read_index -= max_size;
217 run_functor_and_delete(internal_buffer + read_index, internal_buffer + read_index + output_count, functor);
219 if (new_read_index == max_size)
223 read_index_.store(new_read_index, memory_order_release);
227 template <typename Functor>
228 size_t consume_all (Functor & functor, T * internal_buffer, size_t max_size)
230 const size_t write_index = write_index_.load(memory_order_acquire);
231 const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
233 const size_t avail = read_available(write_index, read_index, max_size);
238 const size_t output_count = avail;
240 size_t new_read_index = read_index + output_count;
242 if (read_index + output_count > max_size) {
243 /* copy data in two sections */
244 const size_t count0 = max_size - read_index;
245 const size_t count1 = output_count - count0;
247 run_functor_and_delete(internal_buffer + read_index, internal_buffer + max_size, functor);
248 run_functor_and_delete(internal_buffer, internal_buffer + count1, functor);
250 new_read_index -= max_size;
252 run_functor_and_delete(internal_buffer + read_index, internal_buffer + read_index + output_count, functor);
254 if (new_read_index == max_size)
258 read_index_.store(new_read_index, memory_order_release);
262 size_t pop (T * output_buffer, size_t output_count, T * internal_buffer, size_t max_size)
264 const size_t write_index = write_index_.load(memory_order_acquire);
265 const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
267 const size_t avail = read_available(write_index, read_index, max_size);
272 output_count = (std::min)(output_count, avail);
274 size_t new_read_index = read_index + output_count;
276 if (read_index + output_count > max_size) {
277 /* copy data in two sections */
278 const size_t count0 = max_size - read_index;
279 const size_t count1 = output_count - count0;
281 copy_and_delete(internal_buffer + read_index, internal_buffer + max_size, output_buffer);
282 copy_and_delete(internal_buffer, internal_buffer + count1, output_buffer + count0);
284 new_read_index -= max_size;
286 copy_and_delete(internal_buffer + read_index, internal_buffer + read_index + output_count, output_buffer);
287 if (new_read_index == max_size)
291 read_index_.store(new_read_index, memory_order_release);
295 template <typename OutputIterator>
296 size_t pop_to_output_iterator (OutputIterator it, T * internal_buffer, size_t max_size)
298 const size_t write_index = write_index_.load(memory_order_acquire);
299 const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
301 const size_t avail = read_available(write_index, read_index, max_size);
305 size_t new_read_index = read_index + avail;
307 if (read_index + avail > max_size) {
308 /* copy data in two sections */
309 const size_t count0 = max_size - read_index;
310 const size_t count1 = avail - count0;
312 it = copy_and_delete(internal_buffer + read_index, internal_buffer + max_size, it);
313 copy_and_delete(internal_buffer, internal_buffer + count1, it);
315 new_read_index -= max_size;
317 copy_and_delete(internal_buffer + read_index, internal_buffer + read_index + avail, it);
318 if (new_read_index == max_size)
322 read_index_.store(new_read_index, memory_order_release);
326 const T& front(const T * internal_buffer) const
328 const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
329 return *(internal_buffer + read_index);
332 T& front(T * internal_buffer)
334 const size_t read_index = read_index_.load(memory_order_relaxed); // only written from pop thread
335 return *(internal_buffer + read_index);
341 /** reset the ringbuffer
343 * \note Not thread-safe
347 if ( !boost::has_trivial_destructor<T>::value ) {
348 // make sure to call all destructors!
351 while (pop(dummy_element))
354 write_index_.store(0, memory_order_relaxed);
355 read_index_.store(0, memory_order_release);
359 /** Check if the ringbuffer is empty
361 * \return true, if the ringbuffer is empty, false otherwise
362 * \note Due to the concurrent nature of the ringbuffer the result may be inaccurate.
366 return empty(write_index_.load(memory_order_relaxed), read_index_.load(memory_order_relaxed));
370 * \return true, if implementation is lock-free.
373 bool is_lock_free(void) const
375 return write_index_.is_lock_free() && read_index_.is_lock_free();
379 bool empty(size_t write_index, size_t read_index)
381 return write_index == read_index;
384 template< class OutputIterator >
385 OutputIterator copy_and_delete( T * first, T * last, OutputIterator out )
387 if (boost::has_trivial_destructor<T>::value) {
388 return std::copy(first, last, out); // will use memcpy if possible
390 for (; first != last; ++first, ++out) {
398 template< class Functor >
399 void run_functor_and_delete( T * first, T * last, Functor & functor )
401 for (; first != last; ++first) {
407 template< class Functor >
408 void run_functor_and_delete( T * first, T * last, Functor const & functor )
410 for (; first != last; ++first) {
417 template <typename T, std::size_t MaxSize>
418 class compile_time_sized_ringbuffer:
419 public ringbuffer_base<T>
421 typedef std::size_t size_type;
422 static const std::size_t max_size = MaxSize + 1;
424 typedef typename boost::aligned_storage<max_size * sizeof(T),
425 boost::alignment_of<T>::value
426 >::type storage_type;
428 storage_type storage_;
432 return static_cast<T*>(storage_.address());
435 const T * data() const
437 return static_cast<const T*>(storage_.address());
441 size_type max_number_of_elements() const
447 bool push(T const & t)
449 return ringbuffer_base<T>::push(t, data(), max_size);
452 template <typename Functor>
453 bool consume_one(Functor & f)
455 return ringbuffer_base<T>::consume_one(f, data(), max_size);
458 template <typename Functor>
459 bool consume_one(Functor const & f)
461 return ringbuffer_base<T>::consume_one(f, data(), max_size);
464 template <typename Functor>
465 bool consume_all(Functor & f)
467 return ringbuffer_base<T>::consume_all(f, data(), max_size);
470 template <typename Functor>
471 bool consume_all(Functor const & f)
473 return ringbuffer_base<T>::consume_all(f, data(), max_size);
476 size_type push(T const * t, size_type size)
478 return ringbuffer_base<T>::push(t, size, data(), max_size);
481 template <size_type size>
482 size_type push(T const (&t)[size])
484 return push(t, size);
487 template <typename ConstIterator>
488 ConstIterator push(ConstIterator begin, ConstIterator end)
490 return ringbuffer_base<T>::push(begin, end, data(), max_size);
493 size_type pop(T * ret, size_type size)
495 return ringbuffer_base<T>::pop(ret, size, data(), max_size);
498 template <typename OutputIterator>
499 size_type pop_to_output_iterator(OutputIterator it)
501 return ringbuffer_base<T>::pop_to_output_iterator(it, data(), max_size);
504 const T& front(void) const
506 return ringbuffer_base<T>::front(data());
511 return ringbuffer_base<T>::front(data());
515 template <typename T, typename Alloc>
516 class runtime_sized_ringbuffer:
517 public ringbuffer_base<T>,
520 typedef std::size_t size_type;
521 size_type max_elements_;
522 typedef typename Alloc::pointer pointer;
526 size_type max_number_of_elements() const
528 return max_elements_;
532 explicit runtime_sized_ringbuffer(size_type max_elements):
533 max_elements_(max_elements + 1)
535 array_ = Alloc::allocate(max_elements_);
538 template <typename U>
539 runtime_sized_ringbuffer(typename Alloc::template rebind<U>::other const & alloc, size_type max_elements):
540 Alloc(alloc), max_elements_(max_elements + 1)
542 array_ = Alloc::allocate(max_elements_);
545 runtime_sized_ringbuffer(Alloc const & alloc, size_type max_elements):
546 Alloc(alloc), max_elements_(max_elements + 1)
548 array_ = Alloc::allocate(max_elements_);
551 ~runtime_sized_ringbuffer(void)
553 // destroy all remaining items
555 while (pop(&out, 1)) {}
557 Alloc::deallocate(array_, max_elements_);
560 bool push(T const & t)
562 return ringbuffer_base<T>::push(t, &*array_, max_elements_);
565 template <typename Functor>
566 bool consume_one(Functor & f)
568 return ringbuffer_base<T>::consume_one(f, &*array_, max_elements_);
571 template <typename Functor>
572 bool consume_one(Functor const & f)
574 return ringbuffer_base<T>::consume_one(f, &*array_, max_elements_);
577 template <typename Functor>
578 size_type consume_all(Functor & f)
580 return ringbuffer_base<T>::consume_all(f, &*array_, max_elements_);
583 template <typename Functor>
584 size_type consume_all(Functor const & f)
586 return ringbuffer_base<T>::consume_all(f, &*array_, max_elements_);
589 size_type push(T const * t, size_type size)
591 return ringbuffer_base<T>::push(t, size, &*array_, max_elements_);
594 template <size_type size>
595 size_type push(T const (&t)[size])
597 return push(t, size);
600 template <typename ConstIterator>
601 ConstIterator push(ConstIterator begin, ConstIterator end)
603 return ringbuffer_base<T>::push(begin, end, array_, max_elements_);
606 size_type pop(T * ret, size_type size)
608 return ringbuffer_base<T>::pop(ret, size, array_, max_elements_);
611 template <typename OutputIterator>
612 size_type pop_to_output_iterator(OutputIterator it)
614 return ringbuffer_base<T>::pop_to_output_iterator(it, array_, max_elements_);
617 const T& front(void) const
619 return ringbuffer_base<T>::front(array_);
624 return ringbuffer_base<T>::front(array_);
628 template <typename T, typename A0, typename A1>
629 struct make_ringbuffer
631 typedef typename ringbuffer_signature::bind<A0, A1>::type bound_args;
633 typedef extract_capacity<bound_args> extract_capacity_t;
635 static const bool runtime_sized = !extract_capacity_t::has_capacity;
636 static const size_t capacity = extract_capacity_t::capacity;
638 typedef extract_allocator<bound_args, T> extract_allocator_t;
639 typedef typename extract_allocator_t::type allocator;
641 // allocator argument is only sane, for run-time sized ringbuffers
642 BOOST_STATIC_ASSERT((mpl::if_<mpl::bool_<!runtime_sized>,
643 mpl::bool_<!extract_allocator_t::has_allocator>,
647 typedef typename mpl::if_c<runtime_sized,
648 runtime_sized_ringbuffer<T, allocator>,
649 compile_time_sized_ringbuffer<T, capacity>
650 >::type ringbuffer_type;
654 } /* namespace detail */
657 /** The spsc_queue class provides a single-writer/single-reader fifo queue, pushing and popping is wait-free.
660 * - \c boost::lockfree::capacity<>, optional <br>
661 * If this template argument is passed to the options, the size of the ringbuffer is set at compile-time.
663 * - \c boost::lockfree::allocator<>, defaults to \c boost::lockfree::allocator<std::allocator<T>> <br>
664 * Specifies the allocator that is used to allocate the ringbuffer. This option is only valid, if the ringbuffer is configured
665 * to be sized at run-time
668 * - T must have a default constructor
669 * - T must be copyable
671 #ifndef BOOST_DOXYGEN_INVOKED
672 template <typename T,
673 class A0 = boost::parameter::void_,
674 class A1 = boost::parameter::void_>
676 template <typename T, ...Options>
679 public detail::make_ringbuffer<T, A0, A1>::ringbuffer_type
683 #ifndef BOOST_DOXYGEN_INVOKED
684 typedef typename detail::make_ringbuffer<T, A0, A1>::ringbuffer_type base_type;
685 static const bool runtime_sized = detail::make_ringbuffer<T, A0, A1>::runtime_sized;
686 typedef typename detail::make_ringbuffer<T, A0, A1>::allocator allocator_arg;
688 struct implementation_defined
690 typedef allocator_arg allocator;
691 typedef std::size_t size_type;
696 typedef T value_type;
697 typedef typename implementation_defined::allocator allocator;
698 typedef typename implementation_defined::size_type size_type;
700 /** Constructs a spsc_queue
702 * \pre spsc_queue must be configured to be sized at compile-time
707 BOOST_ASSERT(!runtime_sized);
710 template <typename U>
711 explicit spsc_queue(typename allocator::template rebind<U>::other const & alloc)
713 // just for API compatibility: we don't actually need an allocator
714 BOOST_STATIC_ASSERT(!runtime_sized);
717 explicit spsc_queue(allocator const & alloc)
719 // just for API compatibility: we don't actually need an allocator
720 BOOST_ASSERT(!runtime_sized);
725 /** Constructs a spsc_queue for element_count elements
727 * \pre spsc_queue must be configured to be sized at run-time
730 explicit spsc_queue(size_type element_count):
731 base_type(element_count)
733 BOOST_ASSERT(runtime_sized);
736 template <typename U>
737 spsc_queue(size_type element_count, typename allocator::template rebind<U>::other const & alloc):
738 base_type(alloc, element_count)
740 BOOST_STATIC_ASSERT(runtime_sized);
743 spsc_queue(size_type element_count, allocator_arg const & alloc):
744 base_type(alloc, element_count)
746 BOOST_ASSERT(runtime_sized);
750 /** Pushes object t to the ringbuffer.
752 * \pre only one thread is allowed to push data to the spsc_queue
753 * \post object will be pushed to the spsc_queue, unless it is full.
754 * \return true, if the push operation is successful.
756 * \note Thread-safe and wait-free
758 bool push(T const & t)
760 return base_type::push(t);
763 /** Pops one object from ringbuffer.
765 * \pre only one thread is allowed to pop data to the spsc_queue
766 * \post if ringbuffer is not empty, object will be discarded.
767 * \return true, if the pop operation is successful, false if ringbuffer was empty.
769 * \note Thread-safe and wait-free
773 detail::consume_noop consume_functor;
774 return consume_one( consume_functor );
777 /** Pops one object from ringbuffer.
779 * \pre only one thread is allowed to pop data to the spsc_queue
780 * \post if ringbuffer is not empty, object will be copied to ret.
781 * \return true, if the pop operation is successful, false if ringbuffer was empty.
783 * \note Thread-safe and wait-free
785 template <typename U>
786 typename boost::enable_if<typename is_convertible<T, U>::type, bool>::type
789 detail::consume_via_copy<U> consume_functor(ret);
790 return consume_one( consume_functor );
793 /** Pushes as many objects from the array t as there is space.
795 * \pre only one thread is allowed to push data to the spsc_queue
796 * \return number of pushed items
798 * \note Thread-safe and wait-free
800 size_type push(T const * t, size_type size)
802 return base_type::push(t, size);
805 /** Pushes as many objects from the array t as there is space available.
807 * \pre only one thread is allowed to push data to the spsc_queue
808 * \return number of pushed items
810 * \note Thread-safe and wait-free
812 template <size_type size>
813 size_type push(T const (&t)[size])
815 return push(t, size);
818 /** Pushes as many objects from the range [begin, end) as there is space .
820 * \pre only one thread is allowed to push data to the spsc_queue
821 * \return iterator to the first element, which has not been pushed
823 * \note Thread-safe and wait-free
825 template <typename ConstIterator>
826 ConstIterator push(ConstIterator begin, ConstIterator end)
828 return base_type::push(begin, end);
831 /** Pops a maximum of size objects from ringbuffer.
833 * \pre only one thread is allowed to pop data to the spsc_queue
834 * \return number of popped items
836 * \note Thread-safe and wait-free
838 size_type pop(T * ret, size_type size)
840 return base_type::pop(ret, size);
843 /** Pops a maximum of size objects from spsc_queue.
845 * \pre only one thread is allowed to pop data to the spsc_queue
846 * \return number of popped items
848 * \note Thread-safe and wait-free
850 template <size_type size>
851 size_type pop(T (&ret)[size])
853 return pop(ret, size);
856 /** Pops objects to the output iterator it
858 * \pre only one thread is allowed to pop data to the spsc_queue
859 * \return number of popped items
861 * \note Thread-safe and wait-free
863 template <typename OutputIterator>
864 typename boost::disable_if<typename is_convertible<T, OutputIterator>::type, size_type>::type
865 pop(OutputIterator it)
867 return base_type::pop_to_output_iterator(it);
870 /** consumes one element via a functor
872 * pops one element from the queue and applies the functor on this object
874 * \returns true, if one element was consumed
876 * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking
878 template <typename Functor>
879 bool consume_one(Functor & f)
881 return base_type::consume_one(f);
884 /// \copydoc boost::lockfree::spsc_queue::consume_one(Functor & rhs)
885 template <typename Functor>
886 bool consume_one(Functor const & f)
888 return base_type::consume_one(f);
891 /** consumes all elements via a functor
893 * sequentially pops all elements from the queue and applies the functor on each object
895 * \returns number of elements that are consumed
897 * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking
899 template <typename Functor>
900 size_type consume_all(Functor & f)
902 return base_type::consume_all(f);
905 /// \copydoc boost::lockfree::spsc_queue::consume_all(Functor & rhs)
906 template <typename Functor>
907 size_type consume_all(Functor const & f)
909 return base_type::consume_all(f);
912 /** get number of elements that are available for read
914 * \return number of available elements that can be popped from the spsc_queue
916 * \note Thread-safe and wait-free, should only be called from the producer thread
918 size_type read_available() const
920 return base_type::read_available(base_type::max_number_of_elements());
923 /** get write space to write elements
925 * \return number of elements that can be pushed to the spsc_queue
927 * \note Thread-safe and wait-free, should only be called from the consumer thread
929 size_type write_available() const
931 return base_type::write_available(base_type::max_number_of_elements());
934 /** get reference to element in the front of the queue
936 * Availability of front element can be checked using read_available().
938 * \pre only one thread is allowed to check front element
939 * \pre read_available() > 0. If ringbuffer is empty, it's undefined behaviour to invoke this method.
940 * \return reference to the first element in the queue
942 * \note Thread-safe and wait-free
944 const T& front() const
946 BOOST_ASSERT(read_available() > 0);
947 return base_type::front();
950 /// \copydoc boost::lockfree::spsc_queue::front() const
953 BOOST_ASSERT(read_available() > 0);
954 return base_type::front();
958 } /* namespace lockfree */
959 } /* namespace boost */
962 #endif /* BOOST_LOCKFREE_SPSC_QUEUE_HPP_INCLUDED */