From d37900ad468b79d70e7f692c08ae9028e3e1f184 Mon Sep 17 00:00:00 2001 From: khizmax Date: Sun, 12 Oct 2014 18:40:42 +0400 Subject: [PATCH] VyukovMPMCCycleQueue refactoring --- cds/container/tsigas_cycle_queue.h | 13 +- cds/container/vyukov_mpmc_cycle_queue.h | 303 ++++++++++-------- cds/intrusive/vyukov_mpmc_cycle_queue.h | 137 +++++--- cds/memory/michael/allocator.h | 12 +- cds/memory/vyukov_queue_pool.h | 91 +++--- cds/urcu/details/gpb.h | 5 +- cds/urcu/details/gpt.h | 5 +- cds/urcu/details/sig_buffered.h | 5 +- cds/urcu/details/sig_threaded.h | 5 +- cds/urcu/general_buffered.h | 5 +- cds/urcu/general_threaded.h | 5 +- cds/urcu/signal_buffered.h | 5 +- cds/urcu/signal_threaded.h | 5 +- tests/test-hdr/queue/hdr_intrusive_msqueue.h | 8 +- .../hdr_intrusive_vyukovmpmc_cycle_queue.cpp | 68 ++-- tests/test-hdr/queue/hdr_queue.h | 6 - tests/test-hdr/queue/hdr_queue_new.h | 17 +- .../test-hdr/queue/hdr_tsigas_cycle_queue.cpp | 2 +- .../test-hdr/queue/hdr_vyukov_mpmc_cyclic.cpp | 63 ++-- .../hdr_intrusive_ellen_bintree_pool_hp.h | 21 +- .../hdr_intrusive_ellen_bintree_pool_ptb.h | 20 +- .../hdr_intrusive_ellen_bintree_pool_rcu.h | 27 +- tests/unit/ellen_bintree_update_desc_pool.h | 21 +- tests/unit/queue/intrusive_queue_type.h | 34 +- tests/unit/queue/queue_type.h | 44 ++- 25 files changed, 469 insertions(+), 458 deletions(-) diff --git a/cds/container/tsigas_cycle_queue.h b/cds/container/tsigas_cycle_queue.h index fd6b41f5..7c46531a 100644 --- a/cds/container/tsigas_cycle_queue.h +++ b/cds/container/tsigas_cycle_queue.h @@ -19,10 +19,10 @@ namespace cds { namespace container { { /// Buffer type for cyclic array /* - The type of element for the buffer is not important: the queue rebinds - buffer for required type via \p rebind metafunction. + The type of element for the buffer is not important: the queue rebinds + buffer for required type via \p rebind metafunction. - For \p TsigasCycleQueue queue the buffer size should have power-of-2 size. + For \p TsigasCycleQueue queue the buffer size should have power-of-2 size. */ typedef cds::opt::v::dynamic_buffer< void * > buffer; @@ -37,8 +37,8 @@ namespace cds { namespace container { /// C++ memory ordering model /** - Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) - or \p opt::v::sequential_consistent (sequentially consisnent memory model). + Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) + or \p opt::v::sequential_consistent (sequentially consisnent memory model). */ typedef opt::v::relaxed_ordering memory_model; @@ -54,8 +54,6 @@ namespace cds { namespace container { element in the buffer is not important: it will be changed via \p rebind metafunction. - \p opt::allocator - allocator (like \p std::allocator) used for allocating queue items. Default is \ref CDS_DEFAULT_ALLOCATOR - \p opt::back_off - back-off strategy used, default is \p cds::backoff::empty. - - \p opt::disposer - the functor used for dispose removed items. Default is \p opt::v::empty_disposer. This option is used - when dequeuing. - \p opt::item_counter - the type of item counting feature. Default is \p cds::atomicity::empty_item_counter (item counting disabled) To enable item counting use \p cds::atomicity::item_counter - \p opt::alignment - the alignment for internal queue data. Default is \p opt::cache_line_alignment @@ -305,7 +303,6 @@ namespace cds { namespace container { return enqueue_with( f ); } - /// Dequeues a value using a functor /** \p Func is a functor called to copy dequeued value. diff --git a/cds/container/vyukov_mpmc_cycle_queue.h b/cds/container/vyukov_mpmc_cycle_queue.h index 2c2a7bf9..30095b70 100644 --- a/cds/container/vyukov_mpmc_cycle_queue.h +++ b/cds/container/vyukov_mpmc_cycle_queue.h @@ -3,16 +3,95 @@ #ifndef __CDS_CONTAINER_VYUKOV_MPMC_CYCLE_QUEUE_H #define __CDS_CONTAINER_VYUKOV_MPMC_CYCLE_QUEUE_H -#include // ref #include #include #include #include -#include #include namespace cds { namespace container { + /// VyukovMPMCCycleQueue related definitions + /** @ingroup cds_nonintrusive_helper + */ + namespace vyukov_queue { + + /// VyukovMPMCCycleQueue default traits + struct traits { + /// Buffer type for internal array + /* + The type of element for the buffer is not important: the queue rebinds + buffer for required type via \p rebind metafunction. + + For \p VyukovMPMCCycleQueue queue the buffer size should have power-of-2 size. + */ + typedef cds::opt::v::dynamic_buffer< void * > buffer; + + /// A functor to clean item dequeued. + /** + The functor calls the destructor for queue item. + After an item is dequeued, \p value_cleaner cleans the cell that the item has been occupied. + If \p T is a complex type, \p value_cleaner may be the useful feature. + + Default value is \ref opt::v::destruct_cleaner + */ + typedef cds::opt::v::destruct_cleaner value_cleaner; + + /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter to enable item counting + typedef cds::atomicity::empty_item_counter item_counter; + + /// C++ memory ordering model + /** + Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) + or \p opt::v::sequential_consistent (sequentially consisnent memory model). + */ + typedef opt::v::relaxed_ordering memory_model; + + /// Alignment for internal queue data. Default is \p opt::cache_line_alignment + enum { alignment = opt::cache_line_alignment }; + }; + + /// Metafunction converting option list to \p vyukov_queue::traits + /** + Supported \p Options are: + - \p opt::buffer - the buffer type for internal cyclic array. Possible types are: + \p opt::v::dynamic_buffer (the default), \p opt::v::static_buffer. The type of + element in the buffer is not important: it will be changed via \p rebind metafunction. + - \p opt::value_cleaner - a functor to clean item dequeued. + The functor calls the destructor for queue item. + After an item is dequeued, \p value_cleaner cleans the cell that the item has been occupied. + If \p T is a complex type, \p value_cleaner may be the useful feature. + Default value is \ref opt::v::destruct_cleaner + - \p opt::item_counter - the type of item counting feature. Default is \p cds::atomicity::empty_item_counter (item counting disabled) + To enable item counting use \p cds::atomicity::item_counter + - \p opt::alignment - the alignment for internal queue data. Default is \p opt::cache_line_alignment + - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) + or \p opt::v::sequential_consistent (sequentially consisnent memory model). + + Example: declare \p %VyukovMPMCCycleQueue with item counting and static iternal buffer of size 1024: + \code + typedef cds::container::VyukovMPMCCycleQueue< Foo, + typename cds::container::vyukov_queue::make_traits< + cds::opt::buffer< cds::opt::v::static_buffer< void *, 1024 >, + cds::opt::item_counte< cds::atomicity::item_counter > + >::type + > myQueue; + \endcode + */ + template + struct make_traits { +# ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined type; ///< Metafunction result +# else + typedef typename cds::opt::make_options< + typename cds::opt::find_type_traits< traits, Options... >::type + , Options... + >::type type; +# endif + }; + + } //namespace vyukov_queue + /// Vyukov's MPMC bounded queue /** @ingroup cds_nonintrusive_queue This algorithm is developed by Dmitry Vyukov (see http://www.1024cores.net) @@ -24,76 +103,44 @@ namespace cds { namespace container { No dynamic memory allocation/management during operation. Producers and consumers are separated from each other (as in the two-lock queue), i.e. do not touch the same data while queue is not empty. - \par Source: - http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue - - \par Template parameters - \li \p T - type stored in queue. - \li \p Options - queue's options + Source: + - http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue - Options \p Options are: - - opt::buffer - buffer to store items. Mandatory option, see option description for full list of possible types. - - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter - - opt::value_cleaner - a functor to clean item dequeued. Default value is \ref opt::v::destruct_cleaner - that calls the destructor of type \p T. - After an item is dequeued, \p value_cleaner cleans the cell that the item has been occupied. If \p T - is a complex type, \p value_cleaner may be the useful feature. - - opt::alignment - the alignment for internal queue data. Default is opt::cache_line_alignment - - opt::memory_model - C++ memory ordering model. Can be opt::v::relaxed_ordering (relaxed memory model, the default) - or opt::v::sequential_consistent (sequentially consisnent memory model). + Template parameters + - \p T - type stored in queue. + - \p Traits - queue traits, default is \p vykov_queue::traits. You can use \p vykov_queue::make_traits + metafunction to make your traits or just derive your traits from \p %vykov_queue::traits: + \code + struct myTraits: public cds::container::vykov_queue::traits { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::container::VyukovMPMCCycleQueue< Foo, myTraits > myQueue; + + // Equivalent make_traits example: + typedef cds::container::VyukovMPMCCycleQueue< cds::gc::HP, Foo, + typename cds::container::vykov_queue::make_traits< + cds::opt::item_counter< cds::atomicity::item_counter > + >::type + > myQueue; + \endcode \par License Simplified BSD license by Dmitry Vyukov (http://www.1024cores.net/site/1024cores/home/code-license) - - \par Example - \code - #include - - // // Queue with 1024 item static buffer - cds::container::vyukov_mpmc_bounded< - int - ,cds::opt::buffer< cds::opt::v::static_buffer > - > myQueue; - \endcode */ - template - class VyukovMPMCCycleQueue - : public cds::bounded_container + template + class VyukovMPMCCycleQueue : public cds::bounded_container { - protected: - //@cond - struct default_options - { - typedef cds::opt::v::destruct_cleaner value_cleaner; - typedef atomicity::empty_item_counter item_counter; - typedef opt::v::empty_disposer disposer ; // for intrusive version only - typedef opt::v::relaxed_ordering memory_model; - enum { alignment = opt::cache_line_alignment }; - }; - //@endcond - - public: - //@cond - typedef typename opt::make_options< - typename cds::opt::find_type_traits< default_options, Options... >::type - ,Options... - >::type options; - //@endcond - - protected: - //@cond - typedef typename options::value_cleaner value_cleaner; - //@endcond - public: - typedef T value_type ; ///< @anchor cds_container_VyukovMPMCCycleQueue_value_type type of value stored in the queue - typedef typename options::item_counter item_counter ; ///< Item counter type - typedef typename options::memory_model memory_model ; ///< Memory ordering. See cds::opt::memory_model option + typedef T value_type; ///< Value type to be stored in the queue + typedef Traits traits; ///< Queue traits + typedef typename traits::item_counter item_counter; ///< Item counter type + typedef typename traits::memory_model memory_model; ///< Memory ordering. See cds::opt::memory_model option + typedef typename traits::value_cleaner value_cleaner; ///< Value cleaner, see \p vyukov_queue::traits::value_cleaner /// Rebind template arguments - template + template struct rebind { - typedef VyukovMPMCCycleQueue< T2, Options2...> other ; ///< Rebinding result + typedef VyukovMPMCCycleQueue< T2, Traits2 > other ; ///< Rebinding result }; protected: @@ -108,11 +155,9 @@ namespace cds { namespace container { {} }; - typedef cds::details::trivial_assign< value_type, value_type > copy_assign; - - typedef typename options::buffer::template rebind::other buffer; - typedef typename opt::details::alignment_setter< sequence_type, options::alignment >::type aligned_sequence_type; - typedef typename opt::details::alignment_setter< buffer, options::alignment >::type aligned_buffer; + typedef typename traits::buffer::template rebind::other buffer; + typedef typename opt::details::alignment_setter< sequence_type, traits::alignment >::type aligned_sequence_type; + typedef typename opt::details::alignment_setter< buffer, traits::alignment >::type aligned_buffer; //@endcond protected: @@ -127,7 +172,7 @@ namespace cds { namespace container { public: /// Constructs the queue of capacity \p nCapacity /** - For cds::opt::v::static_buffer the \p nCapacity parameter is ignored. + For \p cds::opt::v::static_buffer the \p nCapacity parameter is ignored. */ VyukovMPMCCycleQueue( size_t nCapacity = 0 @@ -152,26 +197,18 @@ namespace cds { namespace container { clear(); } - /// Enqueues \p data to queue using copy functor - /** @anchor cds_container_VyukovMPMCCycleQueue_enqueue_func - \p Func is a functor called to copy value \p data of type \p Source - which may be differ from type \p T stored in the queue. - The functor's interface is: + /// Enqueues data to the queue using a functor + /** + \p Func is a functor called to copy a value to the queue cell. + The functor \p f takes one argument - a reference to a empty cell of type \ref value_type : \code - struct myFunctor { - void operator()(T& dest, Source const& data) - { - // // Code to copy \p data to \p dest - dest = data; - } - }; + cds::container::VyukovMPMCCycleQueue< Foo > myQueue; + Bar bar; + myQueue.enqueue_with( [&bar]( Foo& dest ) { dest = std::move(bar); } ); \endcode - You may use \p boost:ref construction to pass functor \p f by reference. - - Requirements The functor \p Func should not throw any exception. */ - template - bool enqueue(Source const& data, Func func) + template + bool enqueue_with(Func f) { cell_type* cell; size_t pos = m_posEnqueue.load(memory_model::memory_order_relaxed); @@ -194,7 +231,7 @@ namespace cds { namespace container { pos = m_posEnqueue.load(memory_model::memory_order_relaxed); } - func( cell->data, data ); + f( cell->data ); cell->sequence.store(pos + 1, memory_model::memory_order_release); ++m_ItemCounter; @@ -202,13 +239,30 @@ namespace cds { namespace container { return true; } - /// @anchor cds_container_VyukovMPMCCycleQueue_enqueue Enqueues \p data to queue - bool enqueue(value_type const& data ) + /// Enqueues \p val value into the queue. + /** + The new queue item is created by calling placement new in free cell. + Returns \p true if success, \p false if the queue is full. + */ + bool enqueue( value_type const& val ) { - return enqueue( data, [](value_type& dest, value_type const& src){ new ( &dest ) value_type( src ); }); + return enqueue_with( [&val]( value_type& dest ){ new ( &dest ) value_type( val ); }); } - /// Enqueues data of type \ref cds_container_VyukovMPMCCycleQueue_value_type "value_type" constructed with std::forward(args)... + /// Synonym for \p enqueue() + bool push( value_type const& data ) + { + return enqueue( data ); + } + + /// Synonym for \p enqueue_with() + template + bool push_with( Func f ) + { + return enqueue_with( f ); + } + + /// Enqueues data of type \ref value_type constructed with std::forward(args)... template bool emplace( Args&&... args ) { @@ -241,25 +295,19 @@ namespace cds { namespace container { return true; } - /// Dequeues an item from queue - /** @anchor cds_container_VyukovMPMCCycleQueue_dequeue_func - \p Func is a functor called to copy dequeued value of type \p T to \p dest of type \p Dest. - The functor's interface is: + /// Dequeues a value using a functor + /** + \p Func is a functor called to copy dequeued value. + The functor takes one argument - a reference to removed node: \code - struct myFunctor { - void operator()(Dest& dest, T const& data) - { - // // Code to copy \p data to \p dest - dest = data; - } - }; + cds:container::VyukovMPMCCycleQueue< Foo > myQueue; + Bar bar; + myQueue.dequeue_with( [&bar]( Foo& src ) { bar = std::move( src );}); \endcode - You may use \p boost:ref construction to pass functor \p func by reference. - - Requirements The functor \p Func should not throw any exception. + The functor is called only if the queue is not empty. */ - template - bool dequeue( Dest& data, Func func ) + template + bool dequeue_with( Func f ) { cell_type * cell; size_t pos = m_posDequeue.load(memory_model::memory_order_relaxed); @@ -280,7 +328,7 @@ namespace cds { namespace container { pos = m_posDequeue.load(memory_model::memory_order_relaxed); } - func( data, cell->data ); + f( cell->data ); value_cleaner()( cell->data ); --m_ItemCounter; cell->sequence.store( pos + m_nBufferMask + 1, memory_model::memory_order_release ); @@ -288,39 +336,28 @@ namespace cds { namespace container { return true; } - /// Dequeues an item from queue to \p data - /** @anchor cds_container_VyukovMPMCCycleQueue_dequeue - If queue is empty, returns \p false, \p data is unchanged. + /// Dequeues a value from the queue + /** + If queue is not empty, the function returns \p true, \p dest contains copy of + dequeued value. The assignment operator for type \ref value_type is invoked. + If queue is empty, the function returns \p false, \p dest is unchanged. */ - bool dequeue(value_type & data ) - { - return dequeue( data, copy_assign() ); - } - - /// Synonym of \ref cds_container_VyukovMPMCCycleQueue_enqueue "enqueue" - bool push(value_type const& data) - { - return enqueue(data); - } - - /// Synonym for template version of \ref cds_container_VyukovMPMCCycleQueue_enqueue_func "enqueue" function - template - bool push( const Source& data, Func f ) + bool dequeue(value_type & dest ) { - return enqueue( data, f ); + return dequeue_with( [&dest]( value_type& src ){ dest = src; } ); } - /// Synonym of \ref cds_container_VyukovMPMCCycleQueue_dequeue "dequeue" + /// Synonym for \p dequeue() bool pop(value_type& data) { return dequeue(data); } - /// Synonym for template version of \ref cds_container_VyukovMPMCCycleQueue_dequeue_func "dequeue" function - template - bool pop( Type& dest, Func f ) + /// Synonym for \p dequeue_with() + template + bool pop_with( Func f ) { - return dequeue( dest, f ); + return dequeue_with( f ); } /// Checks if the queue is empty @@ -353,15 +390,15 @@ namespace cds { namespace container { /// Returns queue's item count /** - The value returned depends on opt::item_counter option. For atomicity::empty_item_counter, - this function always returns 0. + The value returned depends on \p vyukov_queue::traits::item_counter option. + For \p atomicity::empty_item_counter, this function always returns 0. */ size_t size() const { return m_ItemCounter.value(); } - /// Returns capacity of cyclic buffer + /// Returns capacity of the queue size_t capacity() const { return m_buffer.capacity(); diff --git a/cds/intrusive/vyukov_mpmc_cycle_queue.h b/cds/intrusive/vyukov_mpmc_cycle_queue.h index 03382df3..0147f543 100644 --- a/cds/intrusive/vyukov_mpmc_cycle_queue.h +++ b/cds/intrusive/vyukov_mpmc_cycle_queue.h @@ -8,25 +8,77 @@ namespace cds { namespace intrusive { + /// VyukovMPMCCycleQueue related definitions + /** @ingroup cds_intrusive_helper + */ + namespace vyukov_queue { + struct traits : public cds::container::vyukov_queue::traits + { + /// The functor used for dispose removed items. Default is \p opt::v::empty_disposer. This option is used only in \p clear() + typedef opt::v::empty_disposer disposer; + }; + + /// Metafunction converting option list to \p vyukov_queue::traits + /** + Supported \p Options are: + - \p opt::buffer - the buffer type for internal cyclic array. Possible types are: + \p opt::v::dynamic_buffer (the default), \p opt::v::static_buffer. The type of + element in the buffer is not important: it will be changed via \p rebind metafunction. + - \p opt::disposer - the functor used for dispose removed items. Default is \p opt::v::empty_disposer. + This option is used only in \p clear() member function. + - \p opt::item_counter - the type of item counting feature. Default is \p cds::atomicity::empty_item_counter (item counting disabled) + To enable item counting use \p cds::atomicity::item_counter + - \p opt::alignment - the alignment for internal queue data. Default is \p opt::cache_line_alignment + - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) + or \p opt::v::sequential_consistent (sequentially consisnent memory model). + + Example: declare \p %VyukovMPMCCycleQueue with item counting and static iternal buffer of size 1024: + \code + typedef cds::intrusive::VyukovMPMCCycleQueue< Foo, + typename cds::intrusive::vyukov_queue::make_traits< + cds::opt::buffer< cds::opt::v::static_buffer< void *, 1024 >, + cds::opt::item_counte< cds::atomicity::item_counter > + >::type + > myQueue; + \endcode + */ + template + struct make_traits { +# ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined type; ///< Metafunction result +# else + typedef typename cds::opt::make_options< + typename cds::opt::find_type_traits< traits, Options... >::type + , Options... + >::type type; +# endif + }; + + } // namespace vyukov_queue + /// Vyukov's MPMC bounded queue /** @ingroup cds_intrusive_queue This algorithm is developed by Dmitry Vyukov (see http://www.1024cores.net) - Implementation of intrusive version is based on non-intrusive class container::VyukovMPMCCycleQueue. + Implementation of intrusive version is based on container::VyukovMPMCCycleQueue. Template parameters: - \p T - type stored in queue. - - \p Options - queue's options - - Options \p Options are: - - opt::buffer - buffer to store items. Mandatory option, see option description for full list of possible types. - - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter - - opt::disposer - the functor used for dispose removed items. Default is opt::v::empty_disposer. This option is used - only in \ref clear function. - - opt::alignment - the alignment for internal queue data. Default is opt::cache_line_alignment - - opt::memory_model - C++ memory ordering model. Can be opt::v::relaxed_ordering (relaxed memory model, the default) - or opt::v::sequential_consistent (sequentially consisnent memory model). - + - \p Traits - queue traits, default is \p vykov_queue::traits. You can use \p vykov_queue::make_traits + metafunction to make your traits or just derive your traits from \p %vykov_queue::traits: + \code + struct myTraits: public cds::intrusive::vykov_queue::traits { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::intrusive::VyukovMPMCCycleQueue< Foo, myTraits > myQueue; + + // Equivalent make_traits example: + typedef cds::intrusive::VyukovMPMCCycleQueue< cds::gc::HP, Foo, + typename cds::intrusive::vykov_queue::make_traits< + cds::opt::item_counter< cds::atomicity::item_counter > + >::type + > myQueue; + \endcode Instead of saving copy of enqueued data, the intrusive implementation stores pointer to passed data. @@ -39,49 +91,47 @@ namespace cds { namespace intrusive { }; // Queue of Foo pointers, capacity is 1024, statically allocated buffer: - typedef cds::intrusive::VyukovMPMCCycleQueue< - Foo - ,cds::opt::buffer< cds::opt::v::static_buffer< Foo, 1024 > > + typedef cds::intrusive::VyukovMPMCCycleQueue< Foo, + typename cds::intrusive::vyukov_queue::make_traits< + cds::opt::buffer< cds::opt::v::static_buffer< Foo, 1024 > > + >::type > static_queue; static_queue stQueue; // Queue of Foo pointers, capacity is 1024, dynamically allocated buffer: - typedef cds::intrusive::VyukovMPMCCycleQueue< - Foo - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< Foo > > - > dynamic_queue; + struct queue_traits: public cds::intrusive::vyukov_queue::traits + { + typedef cds::opt::v::dynamic_buffer< Foo > buffer; + }; + typedef cds::intrusive::VyukovMPMCCycleQueue< Foo, queue_traits > dynamic_queue; dynamic_queue dynQueue( 1024 ); - \endcode */ - template + template class VyukovMPMCCycleQueue - : private container::VyukovMPMCCycleQueue< T *, Options... > + : private container::VyukovMPMCCycleQueue< T*, Traits > { //@cond - typedef container::VyukovMPMCCycleQueue< T *, Options... > base_class; + typedef container::VyukovMPMCCycleQueue< T*, Traits > base_class; //@endcond public: - typedef T value_type ; ///< type of data stored in the queue - typedef typename base_class::item_counter item_counter ; ///< Item counter type - typedef typename base_class::memory_model memory_model ; ///< Memory ordering. See cds::opt::memory_model option - typedef typename base_class::options::disposer disposer ; ///< Item disposer - - //@cond - typedef typename base_class::options options; - //@endcond + typedef T value_type; ///< type of data to be stored in the queue + typedef Traits traits; ///< Queue traits + typedef typename traits::item_counter item_counter; ///< Item counter type + typedef typename traits::memory_model memory_model; ///< Memory ordering. See cds::opt::memory_model option + typedef typename traits::disposer disposer; ///< Item disposer public: /// Rebind template arguments - template + template struct rebind { - typedef VyukovMPMCCycleQueue< T2, Options2...> other ; ///< Rebinding result + typedef VyukovMPMCCycleQueue< T2, Traits2> other ; ///< Rebinding result }; public: /// Constructs the queue of capacity \p nCapacity /** - For cds::opt::v::static_buffer the \p nCapacity parameter is ignored. + For \p cds::opt::v::static_buffer the \p nCapacity parameter is ignored. */ VyukovMPMCCycleQueue( size_t nCapacity = 0 ) : base_class( nCapacity ) @@ -89,7 +139,7 @@ namespace cds { namespace intrusive { /// Enqueues \p data to queue /** - Note that the intrusive queue stores pointer to \p data passed, not the copy of data. + @note The intrusive queue stores pointer to \p data passed, not the copy of \p data. */ bool enqueue( value_type& data ) { @@ -98,6 +148,8 @@ namespace cds { namespace intrusive { /// Dequeues an item from queue /** + \p Traits::disposer is not called. You may manually delete the returned pointer. + If queue is empty, returns \p nullptr. */ value_type * dequeue() @@ -106,13 +158,13 @@ namespace cds { namespace intrusive { return base_class::dequeue( p ) ? p : nullptr; } - /// Synonym of \ref enqueue + /// Synonym for \p enqueue() bool push( value_type& data ) { return enqueue( data ); } - /// Synonym of \ref dequeue + /// Synonym for \p dequeue() value_type * pop() { return dequeue(); @@ -121,7 +173,7 @@ namespace cds { namespace intrusive { /// Clears queue in lock-free manner. /** \p f parameter is a functor to dispose removed items. - The interface of \p DISPOSER is: + The interface of \p Disposer is: \code struct myDisposer { void operator ()( T * val ); @@ -141,7 +193,7 @@ namespace cds { namespace intrusive { /// Clears the queue /** - This function uses the disposer that is specified in \p Options. + This function uses the disposer that is specified in \p Traits. */ void clear() { @@ -154,18 +206,17 @@ namespace cds { namespace intrusive { return base_class::empty(); } - /// Returns queue's item count /** - The value returned depends on opt::item_counter option. For atomicity::empty_item_counter, - this function always returns 0. + The value returned depends on \p vyukov_queue::traits::item_counter option. + For \p atomicity::empty_item_counter, this function always returns 0. */ size_t size() const { return base_class::size(); } - /// Returns capacity of cyclic buffer + /// Returns capacity of the queue size_t capacity() const { return base_class::capacity(); diff --git a/cds/memory/michael/allocator.h b/cds/memory/michael/allocator.h index 35f4ffae..5680f17f 100644 --- a/cds/memory/michael/allocator.h +++ b/cds/memory/michael/allocator.h @@ -145,14 +145,14 @@ namespace michael { } }; #endif - - typedef container::VyukovMPMCCycleQueue< - void *, - opt::buffer< opt::v::static_buffer > + struct free_list_traits : public cds::container::vyukov_queue::traits + { + typedef opt::v::static_buffer buffer; #ifdef _DEBUG - , opt::value_cleaner< make_null_ptr > + typedef make_null_ptr value_cleaner; #endif - > free_list; + }; + typedef container::VyukovMPMCCycleQueue< void *, free_list_traits > free_list; free_list m_FreeList; //@endcond diff --git a/cds/memory/vyukov_queue_pool.h b/cds/memory/vyukov_queue_pool.h index 4eccf9c5..f7c3ceb5 100644 --- a/cds/memory/vyukov_queue_pool.h +++ b/cds/memory/vyukov_queue_pool.h @@ -8,12 +8,20 @@ namespace cds { namespace memory { + /// \p vyukov_queue_pool traits + /** @ingroup cds_memory_pool + */ + struct vyukov_queue_pool_traits : public cds::intrusive::vyukov_queue::traits + { + /// Allocator type + typedef CDS_DEFAULT_ALLOCATOR allocator; + }; /// Free-list based on bounded lock-free queue cds::intrusive::VyukovMPMCCycleQueue /** @ingroup cds_memory_pool Template parameters: - \p T - the type of object maintaining by free-list - - \p Options - the options of cds::intrusive::VyukovMPMCCycleQueue class plus - cds::opt::allocator option. + - \p Traits - traits for cds::intrusive::VyukovMPMCCycleQueue class plus + cds::opt::allocator option, defaul is \p vyukov_queue_pool_traits \b Internals @@ -37,7 +45,11 @@ namespace cds { namespace memory { #include // Pool of Foo object of size 1024. - typedef cds::memory::vyukov_queue_pool< Foo, cds::opt::buffer< cds::opt::v::static_buffer< Foo, 1024 > > pool_type; + struct pool_traits: public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::static_buffer< Foo, 1024 > buffer; + }; + typedef cds::memory::vyukov_queue_pool< Foo, pool_traits > pool_type; static pool_type thePool; struct pool_accessor { @@ -68,24 +80,16 @@ namespace cds { namespace memory { pool_allocator().deallocate( p , 1 ); \endcode */ - template + template class vyukov_queue_pool { public: - typedef cds::intrusive::VyukovMPMCCycleQueue< T, Options... > queue_type ; ///< Queue type - - protected: - //@cond - struct default_options: public queue_type::options - { - typedef CDS_DEFAULT_ALLOCATOR allocator; - }; - typedef typename opt::make_options< default_options, Options... >::type options; - //@endcond + typedef cds::intrusive::VyukovMPMCCycleQueue< T, Traits > queue_type ; ///< Queue type public: typedef T value_type ; ///< Value type - typedef typename options::allocator::template rebind::other allocator_type ; ///< allocator type + typedef Traits traits; ///< Traits type + typedef typename traits::allocator::template rebind::other allocator_type ; ///< allocator type protected: //@cond @@ -173,12 +177,13 @@ namespace cds { namespace memory { } }; + /// Lazy free-list based on bounded lock-free queue cds::intrusive::VyukovMPMCCycleQueue /** @ingroup cds_memory_pool Template parameters: - \p T - the type of object maintaining by free-list - - \p Options - the options of cds::intrusive::VyukovMPMCCycleQueue class plus - cds::opt::allocator option. + - \p Traits - traits for cds::intrusive::VyukovMPMCCycleQueue class plus + cds::opt::allocator option, defaul is \p vyukov_queue_pool_traits \b Internals @@ -201,7 +206,7 @@ namespace cds { namespace memory { #include // Pool of Foo object of size 1024. - typedef cds::memory::lazy_vyukov_queue_pool< Foo, cds::opt::buffer< cds::opt::v::dynamic_buffer< Foo > > pool_type; + typedef cds::memory::lazy_vyukov_queue_pool< Foo > pool_type; static pool_type thePool( 1024 ); struct pool_accessor { @@ -233,24 +238,16 @@ namespace cds { namespace memory { \endcode */ - template + template class lazy_vyukov_queue_pool { public: - typedef cds::intrusive::VyukovMPMCCycleQueue< T, Options... > queue_type ; ///< Queue type - - protected: - //@cond - struct default_options: public queue_type::options - { - typedef CDS_DEFAULT_ALLOCATOR allocator; - }; - typedef typename opt::make_options< default_options, Options... >::type options; - //@endcond + typedef cds::intrusive::VyukovMPMCCycleQueue< T, Traits > queue_type ; ///< Queue type public: typedef T value_type ; ///< Value type - typedef typename options::allocator::template rebind::other allocator_type ; ///< allocator type + typedef Traits traits; ///< Pool traits + typedef typename traits::allocator::template rebind::other allocator_type ; ///< allocator type protected: //@cond @@ -316,19 +313,19 @@ namespace cds { namespace memory { /** @ingroup cds_memory_pool Template parameters: - \p T - the type of object maintaining by free-list - - \p Options - the options of cds::intrusive::VyukovMPMCCycleQueue class plus - cds::opt::allocator option. + - \p Traits - traits for cds::intrusive::VyukovMPMCCycleQueue class plus + cds::opt::allocator option, defaul is \p vyukov_queue_pool_traits \b Internals At construction time, the free-list allocates the array of N items - and stores them into queue, where N is the queue capacity. + and stores them into the queue, where N is the queue capacity. When allocating the free-list tries to pop an object from internal queue i.e. from preallocated pool. If success the popped object is returned. Otherwise a \p std::bad_alloc exception is raised. So, the pool can contain up to \p N items. - When deallocating, the object is pushed into queue. - In debug mode the \ref deallocate member function asserts + When deallocating, the object is pushed into the queue. + In debug mode \p deallocate() member function asserts that the pointer is from preallocated pool. \b Usage @@ -341,7 +338,11 @@ namespace cds { namespace memory { #include // Pool of Foo object of size 1024. - typedef cds::memory::bounded_vyukov_queue_pool< Foo, cds::opt::buffer< cds::opt::v::static_buffer< Foo, 1024 > > pool_type; + struct pool_traits: public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::static_buffer< Foo, 1024 > buffer; + }; + typedef cds::memory::bounded_vyukov_queue_pool< Foo, pool_traits > pool_type; static pool_type thePool; struct pool_accessor { @@ -372,24 +373,16 @@ namespace cds { namespace memory { pool_allocator().deallocate( p , 1 ); \endcode */ - template + template class bounded_vyukov_queue_pool { public: - typedef cds::intrusive::VyukovMPMCCycleQueue< T, Options... > queue_type ; ///< Queue type - - protected: - //@cond - struct default_options: public queue_type::options - { - typedef CDS_DEFAULT_ALLOCATOR allocator; - }; - typedef typename opt::make_options< default_options, Options... >::type options; - //@endcond + typedef cds::intrusive::VyukovMPMCCycleQueue< T, Traits > queue_type ; ///< Queue type public: - typedef T value_type ; ///< Value type - typedef typename options::allocator::template rebind::other allocator_type ; ///< allocator type + typedef T value_type; ///< Value type + typedef Traits traits; ///< Pool traits + typedef typename traits::allocator::template rebind::other allocator_type ; ///< allocator type protected: //@cond diff --git a/cds/urcu/details/gpb.h b/cds/urcu/details/gpb.h index 9e8c4c63..9b0cbd1f 100644 --- a/cds/urcu/details/gpb.h +++ b/cds/urcu/details/gpb.h @@ -39,10 +39,7 @@ namespace cds { namespace urcu { - \p Backoff - back-off schema, default is cds::backoff::Default */ template < - class Buffer = cds::container::VyukovMPMCCycleQueue< - epoch_retired_ptr - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< epoch_retired_ptr > > - > + class Buffer = cds::container::VyukovMPMCCycleQueue< epoch_retired_ptr > ,class Lock = std::mutex ,class Backoff = cds::backoff::Default > diff --git a/cds/urcu/details/gpt.h b/cds/urcu/details/gpt.h index f7712634..8d1031d7 100644 --- a/cds/urcu/details/gpt.h +++ b/cds/urcu/details/gpt.h @@ -38,10 +38,7 @@ namespace cds { namespace urcu { - \p Backoff - back-off schema, default is cds::backoff::Default */ template < - class Buffer = cds::container::VyukovMPMCCycleQueue< - epoch_retired_ptr - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< epoch_retired_ptr > > - > + class Buffer = cds::container::VyukovMPMCCycleQueue< epoch_retired_ptr > ,class Lock = std::mutex ,class DisposerThread = dispose_thread ,class Backoff = cds::backoff::Default diff --git a/cds/urcu/details/sig_buffered.h b/cds/urcu/details/sig_buffered.h index 13786c7d..5737b4ac 100644 --- a/cds/urcu/details/sig_buffered.h +++ b/cds/urcu/details/sig_buffered.h @@ -41,10 +41,7 @@ namespace cds { namespace urcu { - \p Backoff - back-off schema, default is cds::backoff::Default */ template < - class Buffer = cds::container::VyukovMPMCCycleQueue< - epoch_retired_ptr - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< epoch_retired_ptr > > - > + class Buffer = cds::container::VyukovMPMCCycleQueue< epoch_retired_ptr > ,class Lock = std::mutex ,class Backoff = cds::backoff::Default > diff --git a/cds/urcu/details/sig_threaded.h b/cds/urcu/details/sig_threaded.h index 2f5db2e2..9fb2dfe9 100644 --- a/cds/urcu/details/sig_threaded.h +++ b/cds/urcu/details/sig_threaded.h @@ -40,10 +40,7 @@ namespace cds { namespace urcu { - \p Backoff - back-off schema, default is cds::backoff::Default */ template < - class Buffer = cds::container::VyukovMPMCCycleQueue< - epoch_retired_ptr - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< epoch_retired_ptr > > - > + class Buffer = cds::container::VyukovMPMCCycleQueue< epoch_retired_ptr > ,class Lock = std::mutex ,class DisposerThread = dispose_thread ,class Backoff = cds::backoff::Default diff --git a/cds/urcu/general_buffered.h b/cds/urcu/general_buffered.h index 4b042f0e..b55dd2e7 100644 --- a/cds/urcu/general_buffered.h +++ b/cds/urcu/general_buffered.h @@ -20,10 +20,7 @@ namespace cds { namespace urcu { */ template < #ifdef CDS_DOXGEN_INVOKED - class Buffer = cds::container::VyukovMPMCCycleQueue< - retired_ptr - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< retired_ptr > > - > + class Buffer = cds::container::VyukovMPMCCycleQueue< retired_ptr > ,class Lock = std::mutex ,class Backoff = cds::backoff::Default #else diff --git a/cds/urcu/general_threaded.h b/cds/urcu/general_threaded.h index 57699ce1..57e53220 100644 --- a/cds/urcu/general_threaded.h +++ b/cds/urcu/general_threaded.h @@ -23,10 +23,7 @@ namespace cds { namespace urcu { */ template < #ifdef CDS_DOXGEN_INVOKED - class Buffer = cds::container::VyukovMPMCCycleQueue< - epoch_retired_ptr - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< epoch_retired_ptr > > - > + class Buffer = cds::container::VyukovMPMCCycleQueue< epoch_retired_ptr > ,class Lock = std::mutex ,class DisposerThread = dispose_thread ,class Backoff = cds::backoff::Default diff --git a/cds/urcu/signal_buffered.h b/cds/urcu/signal_buffered.h index 0d26dfe4..c62ab3f0 100644 --- a/cds/urcu/signal_buffered.h +++ b/cds/urcu/signal_buffered.h @@ -21,10 +21,7 @@ namespace cds { namespace urcu { */ template < #ifdef CDS_DOXGEN_INVOKED - class Buffer = cds::container::VyukovMPMCCycleQueue< - retired_ptr - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< retired_ptr > > - > + class Buffer = cds::container::VyukovMPMCCycleQueue< retired_ptr > ,class Lock = std::mutex ,class Backoff = cds::backoff::Default #else diff --git a/cds/urcu/signal_threaded.h b/cds/urcu/signal_threaded.h index e8546b01..3d4971db 100644 --- a/cds/urcu/signal_threaded.h +++ b/cds/urcu/signal_threaded.h @@ -25,10 +25,7 @@ namespace cds { namespace urcu { */ template < #ifdef CDS_DOXGEN_INVOKED - class Buffer = cds::container::VyukovMPMCCycleQueue< - epoch_retired_ptr - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< epoch_retired_ptr > > - > + class Buffer = cds::container::VyukovMPMCCycleQueue< epoch_retired_ptr > ,class Lock = std::mutex ,class DisposerThread = dispose_thread ,class Backoff = cds::backoff::Default diff --git a/tests/test-hdr/queue/hdr_intrusive_msqueue.h b/tests/test-hdr/queue/hdr_intrusive_msqueue.h index 8ef8984e..61624b65 100644 --- a/tests/test-hdr/queue/hdr_intrusive_msqueue.h +++ b/tests/test-hdr/queue/hdr_intrusive_msqueue.h @@ -385,8 +385,8 @@ namespace queue { void test_TsigasCycleQueue_dyn(); void test_TsigasCycleQueue_dyn_ic(); - void test_VyukovMPMCCycleQueue_stat(); - void test_VyukovMPMCCycleQueue_stat_ic(); + void test_VyukovMPMCCycleQueue_static(); + void test_VyukovMPMCCycleQueue_static_ic(); void test_VyukovMPMCCycleQueue_dyn(); void test_VyukovMPMCCycleQueue_dyn_ic(); @@ -508,8 +508,8 @@ namespace queue { CPPUNIT_TEST(test_TsigasCycleQueue_dyn) CPPUNIT_TEST(test_TsigasCycleQueue_dyn_ic) - CPPUNIT_TEST(test_VyukovMPMCCycleQueue_stat); - CPPUNIT_TEST(test_VyukovMPMCCycleQueue_stat_ic); + CPPUNIT_TEST(test_VyukovMPMCCycleQueue_static); + CPPUNIT_TEST(test_VyukovMPMCCycleQueue_static_ic); CPPUNIT_TEST(test_VyukovMPMCCycleQueue_dyn); CPPUNIT_TEST(test_VyukovMPMCCycleQueue_dyn_ic); diff --git a/tests/test-hdr/queue/hdr_intrusive_vyukovmpmc_cycle_queue.cpp b/tests/test-hdr/queue/hdr_intrusive_vyukovmpmc_cycle_queue.cpp index e46dc85c..f0a36236 100644 --- a/tests/test-hdr/queue/hdr_intrusive_vyukovmpmc_cycle_queue.cpp +++ b/tests/test-hdr/queue/hdr_intrusive_vyukovmpmc_cycle_queue.cpp @@ -17,53 +17,47 @@ namespace queue { {} }; - typedef ci::VyukovMPMCCycleQueue< - item - ,co::buffer< co::v::static_buffer< int, 1024 > > - ,ci::opt::disposer< IntrusiveQueueHeaderTest::faked_disposer > - ,co::memory_model< co::v::sequential_consistent > - > VyukovMPMCCycleQueue_stat; + struct traits_VyukovMPMCCycleQueue_static : public ci::vyukov_queue::traits + { + typedef co::v::static_buffer< int, 1024 > buffer; + typedef IntrusiveQueueHeaderTest::faked_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::VyukovMPMCCycleQueue< item, traits_VyukovMPMCCycleQueue_static > VyukovMPMCCycleQueue_static; - typedef ci::VyukovMPMCCycleQueue< - item - ,co::buffer< co::v::static_buffer< int, 1024 > > - ,ci::opt::disposer< IntrusiveQueueHeaderTest::faked_disposer > - ,co::item_counter< cds::atomicity::item_counter > - ,co::memory_model< co::v::relaxed_ordering > - > VyukovMPMCCycleQueue_stat_ic; + struct traits_VyukovMPMCCycleQueue_static_ic : public traits_VyukovMPMCCycleQueue_static + { + typedef cds::atomicity::item_counter item_counter; + }; + typedef ci::VyukovMPMCCycleQueue< item, traits_VyukovMPMCCycleQueue_static_ic > VyukovMPMCCycleQueue_static_ic; + struct traits_VyukovMPMCCycleQueue_dyn : + public ci::vyukov_queue::make_traits < + co::buffer< co::v::dynamic_buffer< int > >, + ci::opt::disposer< IntrusiveQueueHeaderTest::faked_disposer > + >::type + {}; class VyukovMPMCCycleQueue_dyn - : public ci::VyukovMPMCCycleQueue< - item - ,co::buffer< co::v::dynamic_buffer< int > > - ,ci::opt::disposer< IntrusiveQueueHeaderTest::faked_disposer > - > + : public ci::VyukovMPMCCycleQueue< item, traits_VyukovMPMCCycleQueue_dyn > { - typedef ci::VyukovMPMCCycleQueue< - item - ,co::buffer< co::v::dynamic_buffer< int > > - ,ci::opt::disposer< IntrusiveQueueHeaderTest::faked_disposer > - > base_class; + typedef ci::VyukovMPMCCycleQueue< item, traits_VyukovMPMCCycleQueue_dyn > base_class; + public: VyukovMPMCCycleQueue_dyn() : base_class( 1024 ) {} }; + struct traits_VyukovMPMCCycleQueue_dyn_ic : + public ci::vyukov_queue::make_traits < + ci::opt::disposer< IntrusiveQueueHeaderTest::faked_disposer > + , co::item_counter< cds::atomicity::item_counter > + >::type + {}; class VyukovMPMCCycleQueue_dyn_ic - : public ci::VyukovMPMCCycleQueue< - item - ,co::buffer< co::v::dynamic_buffer< int > > - ,ci::opt::disposer< IntrusiveQueueHeaderTest::faked_disposer > - ,co::item_counter< cds::atomicity::item_counter > - > + : public ci::VyukovMPMCCycleQueue< item, traits_VyukovMPMCCycleQueue_dyn_ic > { - typedef ci::VyukovMPMCCycleQueue< - item - ,co::buffer< co::v::dynamic_buffer< int > > - ,ci::opt::disposer< IntrusiveQueueHeaderTest::faked_disposer > - ,co::item_counter< cds::atomicity::item_counter > - > base_class; + typedef ci::VyukovMPMCCycleQueue< item, traits_VyukovMPMCCycleQueue_dyn_ic > base_class; public: VyukovMPMCCycleQueue_dyn_ic() : base_class( 1024 ) @@ -71,8 +65,8 @@ namespace queue { }; } - TEST(VyukovMPMCCycleQueue_stat) - TEST(VyukovMPMCCycleQueue_stat_ic) + TEST(VyukovMPMCCycleQueue_static) + TEST(VyukovMPMCCycleQueue_static_ic) TEST(VyukovMPMCCycleQueue_dyn) TEST(VyukovMPMCCycleQueue_dyn_ic) diff --git a/tests/test-hdr/queue/hdr_queue.h b/tests/test-hdr/queue/hdr_queue.h index f213e771..c7c0c9a8 100644 --- a/tests/test-hdr/queue/hdr_queue.h +++ b/tests/test-hdr/queue/hdr_queue.h @@ -148,9 +148,6 @@ namespace queue { void FCQueue_list_mutex(); void FCQueue_list_stat(); - void Vyukov_MPMCCyclicQueue(); - void Vyukov_MPMCCyclicQueue_Counted(); - CPPUNIT_TEST_SUITE(Queue_TestHeader) CPPUNIT_TEST(FCQueue_deque) CPPUNIT_TEST(FCQueue_deque_elimination) @@ -160,9 +157,6 @@ namespace queue { CPPUNIT_TEST(FCQueue_list_elimination) CPPUNIT_TEST(FCQueue_list_mutex) CPPUNIT_TEST(FCQueue_list_stat) - - CPPUNIT_TEST(Vyukov_MPMCCyclicQueue); - CPPUNIT_TEST(Vyukov_MPMCCyclicQueue_Counted); CPPUNIT_TEST_SUITE_END(); }; diff --git a/tests/test-hdr/queue/hdr_queue_new.h b/tests/test-hdr/queue/hdr_queue_new.h index f82fda6c..35cfa0c3 100644 --- a/tests/test-hdr/queue/hdr_queue_new.h +++ b/tests/test-hdr/queue/hdr_queue_new.h @@ -345,10 +345,10 @@ namespace queue { void TsigasCycleQueue_dyn(); void TsigasCycleQueue_dyn_ic(); - /* - void Vyukov_MPMCCyclicQueue(); - void Vyukov_MPMCCyclicQueue_Counted(); - */ + void VyukovMPMCCycleQueue_static(); + void VyukovMPMCCycleQueue_static_ic(); + void VyukovMPMCCycleQueue_dyn(); + void VyukovMPMCCycleQueue_dyn_ic(); CPPUNIT_TEST_SUITE( HdrTestQueue ) CPPUNIT_TEST(MSQueue_HP); @@ -444,10 +444,11 @@ namespace queue { CPPUNIT_TEST( TsigasCycleQueue_dyn ) CPPUNIT_TEST( TsigasCycleQueue_dyn_ic ) -/* - CPPUNIT_TEST(Vyukov_MPMCCyclicQueue); - CPPUNIT_TEST(Vyukov_MPMCCyclicQueue_Counted); -*/ + CPPUNIT_TEST( VyukovMPMCCycleQueue_static ) + CPPUNIT_TEST( VyukovMPMCCycleQueue_static_ic ) + CPPUNIT_TEST( VyukovMPMCCycleQueue_dyn ) + CPPUNIT_TEST( VyukovMPMCCycleQueue_dyn_ic ) + CPPUNIT_TEST( RWQueue_default) CPPUNIT_TEST( RWQueue_mutex ) CPPUNIT_TEST( RWQueue_ic ) diff --git a/tests/test-hdr/queue/hdr_tsigas_cycle_queue.cpp b/tests/test-hdr/queue/hdr_tsigas_cycle_queue.cpp index 787aa51f..2b0b38be 100644 --- a/tests/test-hdr/queue/hdr_tsigas_cycle_queue.cpp +++ b/tests/test-hdr/queue/hdr_tsigas_cycle_queue.cpp @@ -53,7 +53,7 @@ namespace queue { { class queue_type : public cds::container::TsigasCycleQueue< int, - typename cds::container::tsigas_queue::make_traits< + typename cds::container::tsigas_queue::make_traits< cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > , cds::opt::item_counter< cds::atomicity::item_counter > >::type diff --git a/tests/test-hdr/queue/hdr_vyukov_mpmc_cyclic.cpp b/tests/test-hdr/queue/hdr_vyukov_mpmc_cyclic.cpp index cd26d9e9..606ef43e 100644 --- a/tests/test-hdr/queue/hdr_vyukov_mpmc_cyclic.cpp +++ b/tests/test-hdr/queue/hdr_vyukov_mpmc_cyclic.cpp @@ -2,52 +2,45 @@ #include -#include "queue/hdr_queue.h" +#include "queue/hdr_queue_new.h" namespace queue { - namespace { - class VyukovMPMCCyclicQueue_int: - public cds::container::VyukovMPMCCycleQueue< - int, - cds::opt::buffer > - > + namespace{ + struct traits_VyukovMPMCCyclicQueue_static : public cds::container::vyukov_queue::traits { - typedef cds::container::VyukovMPMCCycleQueue< - int, - cds::opt::buffer > - > base_class; - public: - VyukovMPMCCyclicQueue_int() - : base_class(1024 * 32) - {} + typedef cds::opt::v::static_buffer buffer; }; - - class VyukovMPMCCyclicQueue_int_ic: - public cds::container::VyukovMPMCCycleQueue< - int, - cds::opt::buffer >, - cds::opt::item_counter< cds::atomicity::item_counter > - > + struct traits_VyukovMPMCCyclicQueue_static_ic : public traits_VyukovMPMCCyclicQueue_static { - typedef cds::container::VyukovMPMCCycleQueue< - int, - cds::opt::buffer >, - cds::opt::item_counter< cds::atomicity::item_counter > - > base_class; - public: - VyukovMPMCCyclicQueue_int_ic() - : base_class( 32 * 1024 ) - {} + typedef cds::atomicity::item_counter item_counter; }; } + void HdrTestQueue::VyukovMPMCCycleQueue_static() + { + typedef cds::container::VyukovMPMCCycleQueue< int, traits_VyukovMPMCCyclicQueue_static > queue_type; + + test_bounded_no_ic< queue_type >(); + } - void Queue_TestHeader::Vyukov_MPMCCyclicQueue() + void HdrTestQueue::VyukovMPMCCycleQueue_static_ic() { - testNoItemCounter< VyukovMPMCCyclicQueue_int >(); + typedef cds::container::VyukovMPMCCycleQueue< int, traits_VyukovMPMCCyclicQueue_static_ic > queue_type; + test_bounded_ic< queue_type >(); } - void Queue_TestHeader::Vyukov_MPMCCyclicQueue_Counted() + void HdrTestQueue::VyukovMPMCCycleQueue_dyn() { - testWithItemCounter< VyukovMPMCCyclicQueue_int_ic >(); + test_bounded_no_ic< cds::container::VyukovMPMCCycleQueue< int > >(); } + + void HdrTestQueue::VyukovMPMCCycleQueue_dyn_ic() + { + typedef cds::container::VyukovMPMCCycleQueue < int, + typename cds::container::vyukov_queue::make_traits < + cds::opt::item_counter < cds::atomicity::item_counter > + > ::type + > queue_type; + test_bounded_ic< queue_type >(); + } + } diff --git a/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_hp.h b/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_hp.h index f69fb67b..f18a0689 100644 --- a/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_hp.h +++ b/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_hp.h @@ -18,13 +18,12 @@ namespace tree { typedef node_types::internal_node_type internal_node; typedef node_types::update_desc_type update_desc; - // Internal node pool based on Vyukov's queue - typedef cds::memory::lazy_vyukov_queue_pool< - internal_node, - cds::opt::buffer< cds::opt::v::dynamic_buffer< cds::any_type > > - > internal_node_pool_type; - + struct internal_node_pool_traits : public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::dynamic_buffer< cds::any_type > buffer; + }; + typedef cds::memory::lazy_vyukov_queue_pool< internal_node, internal_node_pool_traits > internal_node_pool_type; extern internal_node_pool_type s_InternalNodePool; struct internal_node_pool_accessor { @@ -37,11 +36,11 @@ namespace tree { }; // Update descriptor pool based on Vyukov's queue - typedef cds::memory::vyukov_queue_pool< - update_desc, - cds::opt::buffer< cds::opt::v::static_buffer< cds::any_type, 16 > > - > update_desc_pool_type; - + struct update_desc_pool_traits : public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::static_buffer< cds::any_type, 16 > buffer; + }; + typedef cds::memory::vyukov_queue_pool< update_desc, update_desc_pool_traits > update_desc_pool_type; extern update_desc_pool_type s_UpdateDescPool; struct update_desc_pool_accessor { diff --git a/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_ptb.h b/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_ptb.h index 00fd22af..05d2e9f6 100644 --- a/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_ptb.h +++ b/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_ptb.h @@ -20,11 +20,11 @@ namespace tree { // Internal node pool based on Vyukov's queue - typedef cds::memory::lazy_vyukov_queue_pool< - internal_node, - cds::opt::buffer< cds::opt::v::dynamic_buffer< cds::any_type > > - > internal_node_pool_type; - + struct internal_node_pool_traits : public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::dynamic_buffer< cds::any_type > buffer; + }; + typedef cds::memory::lazy_vyukov_queue_pool< internal_node, internal_node_pool_traits > internal_node_pool_type; extern internal_node_pool_type s_InternalNodePool; struct internal_node_pool_accessor { @@ -37,11 +37,11 @@ namespace tree { }; // Update descriptor pool based on Vyukov's queue - typedef cds::memory::vyukov_queue_pool< - update_desc, - cds::opt::buffer< cds::opt::v::static_buffer< cds::any_type, 16 > > - > update_desc_pool_type; - + struct update_desc_pool_traits : public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::static_buffer< cds::any_type, 16 > buffer; + }; + typedef cds::memory::vyukov_queue_pool< update_desc, update_desc_pool_traits > update_desc_pool_type; extern update_desc_pool_type s_UpdateDescPool; struct update_desc_pool_accessor { diff --git a/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_rcu.h b/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_rcu.h index 32322752..ee2cf627 100644 --- a/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_rcu.h +++ b/tests/test-hdr/tree/hdr_intrusive_ellen_bintree_pool_rcu.h @@ -21,20 +21,13 @@ namespace tree { typedef node_types::internal_node_type internal_node; typedef node_types::update_desc_type update_desc; - /* - typedef cds::intrusive::ellen_bintree::node leaf_node; - typedef IntrusiveBinTreeHdrTest::base_hook_value< leaf_node > base_value; - typedef cds::intrusive::ellen_bintree::internal_node< IntrusiveBinTreeHdrTest::key_type, leaf_node > internal_node; - typedef cds::intrusive::ellen_bintree::update_desc< leaf_node, internal_node > update_desc; - */ - // Internal node pool based on Vyukov's queue - typedef cds::memory::lazy_vyukov_queue_pool< - internal_node, - cds::opt::buffer< cds::opt::v::dynamic_buffer< cds::any_type > > - > internal_node_pool_type; - + struct internal_node_pool_traits : public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::dynamic_buffer< cds::any_type > buffer; + }; + typedef cds::memory::lazy_vyukov_queue_pool< internal_node, internal_node_pool_traits > internal_node_pool_type; extern internal_node_pool_type s_InternalNodePool; struct internal_node_pool_accessor { @@ -47,11 +40,11 @@ namespace tree { }; // Update descriptor pool based on Vyukov's queue - typedef cds::memory::vyukov_queue_pool< - update_desc, - cds::opt::buffer< cds::opt::v::static_buffer< cds::any_type, 16 > > - > update_desc_pool_type; - + struct update_desc_pool_traits : public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::static_buffer< cds::any_type, 16 > buffer; + }; + typedef cds::memory::vyukov_queue_pool< update_desc, update_desc_pool_traits > update_desc_pool_type; extern update_desc_pool_type s_UpdateDescPool; struct update_desc_pool_accessor { diff --git a/tests/unit/ellen_bintree_update_desc_pool.h b/tests/unit/ellen_bintree_update_desc_pool.h index 0887b2f9..cb599f4b 100644 --- a/tests/unit/ellen_bintree_update_desc_pool.h +++ b/tests/unit/ellen_bintree_update_desc_pool.h @@ -9,17 +9,18 @@ #include namespace ellen_bintree_pool { - typedef cds::container::ellen_bintree::node_types< cds::urcu::gc< cds::urcu::general_instant<> >, int > node_types ; // fake + typedef cds::container::ellen_bintree::node_types< cds::urcu::gc< cds::urcu::general_instant<> >, int > node_types; // fake typedef node_types::leaf_node_type leaf_node; typedef node_types::internal_node_type internal_node; typedef node_types::update_desc_type update_desc; // Update descriptor pool based on Vyukov's queue - typedef cds::memory::vyukov_queue_pool< - update_desc, - cds::opt::buffer< cds::opt::v::static_buffer< cds::any_type, 4096 > > - > update_desc_pool_type; + struct update_desc_pool_traits : public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::static_buffer< cds::any_type, 4096 > buffer; + }; + typedef cds::memory::vyukov_queue_pool< update_desc, update_desc_pool_traits > update_desc_pool_type; extern update_desc_pool_type s_UpdateDescPool; struct update_desc_pool_accessor { @@ -32,11 +33,11 @@ namespace ellen_bintree_pool { }; // Update descriptor pool based on bounded Vyukov's queue - typedef cds::memory::bounded_vyukov_queue_pool< - update_desc, - cds::opt::buffer< cds::opt::v::static_buffer< cds::any_type, 4096 > > - > bounded_update_desc_pool_type; - + struct bounded_update_desc_pool_traits : public cds::memory::vyukov_queue_pool_traits + { + typedef cds::opt::v::static_buffer< cds::any_type, 4096 > buffer; + }; + typedef cds::memory::bounded_vyukov_queue_pool< update_desc, bounded_update_desc_pool_traits > bounded_update_desc_pool_type; extern bounded_update_desc_pool_type s_BoundedUpdateDescPool; struct bounded_update_desc_pool_accessor { diff --git a/tests/unit/queue/intrusive_queue_type.h b/tests/unit/queue/intrusive_queue_type.h index d941f50e..67334396 100644 --- a/tests/unit/queue/intrusive_queue_type.h +++ b/tests/unit/queue/intrusive_queue_type.h @@ -271,18 +271,14 @@ namespace queue { }; // VyukovMPMCCycleQueue + struct traits_VyukovMPMCCycleQueue_dyn : public cds::intrusive::vyukov_queue::traits + { + typedef cds::opt::v::dynamic_buffer< int > buffer; + }; class VyukovMPMCCycleQueue_dyn - : public cds::intrusive::VyukovMPMCCycleQueue< T, - typename cds::intrusive::tsigas_queue::make_traits< - cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > - >::type - > + : public cds::intrusive::VyukovMPMCCycleQueue< T, traits_VyukovMPMCCycleQueue_dyn > { - typedef cds::intrusive::VyukovMPMCCycleQueue< T, - typename cds::intrusive::tsigas_queue::make_traits< - cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > - >::type - > base_class; + typedef cds::intrusive::VyukovMPMCCycleQueue< T, traits_VyukovMPMCCycleQueue_dyn > base_class; public: VyukovMPMCCycleQueue_dyn() : base_class( 1024 * 64 ) @@ -297,20 +293,14 @@ namespace queue { } }; + struct traits_VyukovMPMCCycleQueue_dyn_ic : public traits_VyukovMPMCCycleQueue_dyn + { + typedef cds::atomicity::item_counter item_counter; + }; class VyukovMPMCCycleQueue_dyn_ic - : public cds::intrusive::VyukovMPMCCycleQueue< T, - typename cds::intrusive::tsigas_queue::make_traits< - cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > - ,cds::opt::item_counter< cds::atomicity::item_counter > - >::type - > + : public cds::intrusive::VyukovMPMCCycleQueue< T, traits_VyukovMPMCCycleQueue_dyn_ic > { - typedef cds::intrusive::VyukovMPMCCycleQueue< T, - typename cds::intrusive::tsigas_queue::make_traits< - cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > - ,cds::opt::item_counter< cds::atomicity::item_counter > - >::type - > base_class; + typedef cds::intrusive::VyukovMPMCCycleQueue< T, traits_VyukovMPMCCycleQueue_dyn_ic > base_class; public: VyukovMPMCCycleQueue_dyn_ic() : base_class( 1024 * 64 ) diff --git a/tests/unit/queue/queue_type.h b/tests/unit/queue/queue_type.h index 1a7066ed..217a6bf4 100644 --- a/tests/unit/queue/queue_type.h +++ b/tests/unit/queue/queue_type.h @@ -268,16 +268,14 @@ namespace queue { }; // VyukovMPMCCycleQueue + struct traits_VyukovMPMCCycleQueue_dyn : public cds::container::vyukov_queue::traits + { + typedef cds::opt::v::dynamic_buffer< int > buffer; + }; class VyukovMPMCCycleQueue_dyn - : public cds::container::VyukovMPMCCycleQueue< - Value - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > - > + : public cds::container::VyukovMPMCCycleQueue< Value, traits_VyukovMPMCCycleQueue_dyn > { - typedef cds::container::VyukovMPMCCycleQueue< - Value - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > - > base_class; + typedef cds::container::VyukovMPMCCycleQueue< Value, traits_VyukovMPMCCycleQueue_dyn > base_class; public: VyukovMPMCCycleQueue_dyn() : base_class( 1024 * 64 ) @@ -292,16 +290,14 @@ namespace queue { } }; + struct traits_VyukovMPMCCycleQueue_dyn_michaelAlloc : public cds::container::vyukov_queue::traits + { + typedef cds::opt::v::dynamic_buffer< int, memory::MichaelAllocator > buffer; + }; class VyukovMPMCCycleQueue_dyn_michaelAlloc - : public cds::container::VyukovMPMCCycleQueue< - Value - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< int, memory::MichaelAllocator > > - > + : public cds::container::VyukovMPMCCycleQueue< Value, traits_VyukovMPMCCycleQueue_dyn_michaelAlloc > { - typedef cds::container::VyukovMPMCCycleQueue< - Value - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< int, memory::MichaelAllocator > > - > base_class; + typedef cds::container::VyukovMPMCCycleQueue< Value, traits_VyukovMPMCCycleQueue_dyn_michaelAlloc > base_class; public: VyukovMPMCCycleQueue_dyn_michaelAlloc() : base_class( 1024 * 64 ) @@ -316,18 +312,14 @@ namespace queue { } }; + struct traits_VyukovMPMCCycleQueue_dyn_ic : public traits_VyukovMPMCCycleQueue_dyn + { + typedef cds::atomicity::item_counter item_counter; + }; class VyukovMPMCCycleQueue_dyn_ic - : public cds::container::VyukovMPMCCycleQueue< - Value - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > - ,cds::opt::item_counter< cds::atomicity::item_counter > - > + : public cds::container::VyukovMPMCCycleQueue< Value, traits_VyukovMPMCCycleQueue_dyn_ic > { - typedef cds::container::VyukovMPMCCycleQueue< - Value - ,cds::opt::buffer< cds::opt::v::dynamic_buffer< int > > - ,cds::opt::item_counter< cds::atomicity::item_counter > - > base_class; + typedef cds::container::VyukovMPMCCycleQueue< Value, traits_VyukovMPMCCycleQueue_dyn_ic > base_class; public: VyukovMPMCCycleQueue_dyn_ic() : base_class( 1024 * 64 ) -- 2.34.1