+++ /dev/null
-//$$CDS-header$$
-
-#ifndef __CDS_CONTAINER_MICHAEL_DEQUE_H
-#define __CDS_CONTAINER_MICHAEL_DEQUE_H
-
-#include <memory>
-#include <cds/intrusive/michael_deque.h>
-#include <cds/details/trivial_assign.h>
-
-namespace cds { namespace container {
-
- //@cond
- namespace details {
- template <typename GC, typename T, CDS_DECL_OPTIONS7>
- struct make_michael_deque
- {
- typedef GC gc;
- typedef T value_type;
-
- struct default_options
- {
- typedef cds::backoff::empty back_off;
- typedef cds::atomicity::empty_item_counter item_counter;
- typedef cds::intrusive::michael_deque::dummy_stat stat;
- typedef cds::opt::v::relaxed_ordering memory_model;
- enum { alignment = cds::opt::cache_line_alignment };
- typedef CDS_DEFAULT_ALLOCATOR allocator;
- };
-
- typedef typename cds::opt::make_options<
- typename cds::opt::find_type_traits< default_options, CDS_OPTIONS7 >::type
- ,CDS_OPTIONS7
- >::type options;
-
- struct node_type : public cds::intrusive::michael_deque::node< gc >
- {
- value_type m_value;
- node_type()
- {}
- node_type(const value_type& val)
- : m_value( val )
- {}
-# ifdef CDS_EMPLACE_SUPPORT
- template <typename... Args>
- node_type( Args&&... args )
- : m_value( std::forward<Args>(args)...)
- {}
-# endif
- };
-
- typedef typename options::allocator::template rebind<node_type>::other allocator_type;
- typedef cds::details::Allocator< node_type, allocator_type > cxx_allocator;
-
- struct node_deallocator
- {
- void operator ()( node_type * pNode )
- {
- cxx_allocator().Delete( pNode );
- }
- };
-
- typedef cds::intrusive::MichaelDeque< gc,
- node_type
- ,cds::intrusive::opt::hook<
- cds::intrusive::michael_deque::base_hook< cds::opt::gc<gc> >
- >
- ,cds::opt::back_off< typename options::back_off >
- ,cds::intrusive::opt::disposer< node_deallocator >
- ,cds::opt::item_counter< typename options::item_counter >
- ,cds::opt::stat< typename options::stat >
- ,cds::opt::alignment< options::alignment >
- ,cds::opt::memory_model< typename options::memory_model >
- > type;
- };
- }
- //@endcond
-
- /// Michael's deque
- /** @ingroup cds_nonintrusive_deque
-
- Implementation of Michael's deque algorithm.
-
- \par Source:
- [2003] Maged Michael "CAS-based Lock-free Algorithm for Shared Deque"
-
- <b>Short description</b> (from Michael's paper)
-
- The deque is represented as a doubly-linked list. Each node in the list contains two link pointers,
- \p pRight and \p pLeft, and a data field. A shared variable, \p Anchor, holds the two anchor
- pointers to the leftmost and rightmost nodes in the list, if any, and a three-value
- status tag. Anchor must fit in a memory block that can be read and manipulated
- using CAS or LL/SC, atomically. Initially both anchor pointers have null values
- and the status tag holds the value stable, indicating an empty deque.
-
- The status tag serves to indicate if the deque is in an unstable state. When
- a process finds the deque in an unstable state, it must first attempt to take it
- to a stable state before attempting its own operation.
-
- The algorithm can use 64bit CAS. Instead of a pointer the node contains two
- 31bit link indices + one bit for status tag;
- this trick allows use 64bit CAS to manipulate \p Anchor. Internal mapper
- (based on intrusive::MichaelHashSet intrusive container)
- reflects link indices to item pointers. The maximum number of item in
- the deque is limited by <tt>2**31 - 1</tt> that is practically unbounded.
-
- Template arguments:
- - \p GC - garbage collector type: gc::HP, gc::PTB. Note that gc::HRC is <b>NOT</b> supported for this container.
- - \p T is a type stored in the queue. It should be default-constructible, copy-constructible, assignable type.
- - \p Options - options
-
- Permissible \p Options:
- - opt::allocator - allocator (like \p std::allocator). Default is \ref CDS_DEFAULT_ALLOCATOR.
- Used for item allocation.
- - opt::back_off - back-off strategy used. If the option is not specified, the cds::backoff::empty is used
- - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter that means no item counting feature
- - opt::stat - the type to gather internal statistics.
- Possible option value are: \ref intrusive::michael_deque::stat, \ref intrusive::michael_deque::dummy_stat,
- user-provided class that supports intrusive::michael_deque::stat interface.
- Default is \ref intrusive::michael_deque::dummy_stat.
- - opt::alignment - the alignment for internal deque 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 <typename GC, typename T, CDS_DECL_OPTIONS7>
- class MichaelDeque:
-#ifdef CDS_DOXYGEN_INVOKED
- intrusive::MichaelDeque< GC, intrusive::michael_deque::node< T >, Options... >
-#else
- details::make_michael_deque< GC, T, CDS_OPTIONS7 >::type
-#endif
- {
- //@cond
- typedef details::make_michael_deque< GC, T, CDS_OPTIONS7 > options;
- typedef typename options::type base_class;
- //@endcond
-
- public:
- /// Rebind template arguments
- template <typename GC2, typename T2, CDS_DECL_OTHER_OPTIONS7>
- struct rebind {
- typedef MichaelDeque< GC2, T2, CDS_OTHER_OPTIONS7> other ; ///< Rebinding result
- };
-
- public:
- typedef T value_type ; ///< Value type stored in the deque
-
- typedef typename base_class::gc gc ; ///< Garbage collector used
- typedef typename base_class::back_off back_off ; ///< Back-off strategy used
- typedef typename options::allocator_type allocator_type ; ///< Allocator type used for allocate/deallocate the nodes
- typedef typename options::options::item_counter item_counter ; ///< Item counting policy used
- typedef typename options::options::stat stat ; ///< Internal statistics policy used
- typedef typename base_class::memory_model memory_model ; ///< Memory ordering. See cds::opt::memory_model option
-
- protected:
- typedef typename options::node_type node_type ; ///< queue node type (derived from intrusive::single_link::node)
-
- //@cond
- typedef typename options::cxx_allocator cxx_allocator;
- typedef typename options::node_deallocator node_deallocator; // deallocate node
- typedef typename base_class::node_traits node_traits;
- //@endcond
-
- protected:
- ///@cond
- static node_type * alloc_node()
- {
- return cxx_allocator().New();
- }
- static node_type * alloc_node( const value_type& val )
- {
- return cxx_allocator().New( val );
- }
-# ifdef CDS_EMPLACE_SUPPORT
- template <typename... Args>
- static node_type * alloc_node( Args&&... args )
- {
- return cxx_allocator().MoveNew( std::forward<Args>(args)... );
- }
-# endif
- static void free_node( node_type * p )
- {
- node_deallocator()( p );
- }
-
- struct node_disposer {
- void operator()( node_type * pNode )
- {
- free_node( pNode );
- }
- };
- typedef std::unique_ptr< node_type, node_disposer > scoped_node_ptr;
-
- bool push_node_back( node_type * pNode )
- {
- assert( pNode != nullptr );
- scoped_node_ptr p(pNode);
-
- if ( base_class::push_back( *pNode ) ) {
- p.release();
- return true;
- }
- return false;
- }
-
- bool push_node_front( node_type * pNode )
- {
- assert( pNode != nullptr );
- scoped_node_ptr p(pNode);
-
- if ( base_class::push_front( *pNode ) ) {
- p.release();
- return true;
- }
- return false;
- }
- //@endcond
-
- public:
- /// Default constructor
- /**
- Initializes the deque object that can contain up to <tt>2**16 - 1</tt> items
- */
- MichaelDeque()
- {}
-
- /// Constructor
- /**
- Initializes the deque object with estimated item count \p nMaxItemCount.
- \p nLoadFactor is a parameter of internal memory mapper based on intrusive::MichaelHashSet;
- see MichaelHashSet ctor for details
- */
- MichaelDeque( unsigned int nMaxItemCount, unsigned int nLoadFactor = 4 )
- : base_class( nMaxItemCount, nLoadFactor )
- {}
-
- /// Destructor clears the deque
- ~MichaelDeque()
- {}
-
- public:
- /// Push back (right) side
- /**
- Push new item \p val to right side of the deque.
- */
- bool push_back( value_type const& val )
- {
- return push_node_back( alloc_node( val ));
- }
-
- /// Push back (right) side using copy functor
- /**
- \p Func is a functor called to copy value \p data of type \p Type
- which may be differ from type \p T stored in the deque.
- The functor's interface is:
- \code
- struct myFunctor {
- void operator()(T& dest, Type const& data)
- {
- // Code to copy \p data to \p dest
- dest = data;
- }
- };
- \endcode
- You may use \p boost:ref construction to pass functor \p f by reference.
-
- <b>Requirements</b> The functor \p Func should not throw any exception.
- */
- template <typename Type, typename Func>
- bool push_back( Type const& val, Func f )
- {
- scoped_node_ptr p( alloc_node());
- unref(f)( p->m_value, val );
- if ( base_class::push_back( *p )) {
- p.release();
- return true;
- }
- return false;
- }
-
-# ifdef CDS_EMPLACE_SUPPORT
- /// Push back (right side) data of type \ref value_type constructed with <tt>std::forward<Args>(args)...</tt>
- /**
- Returns \p true if the oprration successful, \p false otherwise.
-
- This function is available only for compiler that supports
- variadic template and move semantics
- */
- template <typename... Args>
- bool emplace_back( Args&&... args )
- {
- return push_node_back( alloc_node( std::forward<Args>(args)... ));
- }
-# endif
-
- /// Push front (left) side
- /**
- Push new item \p val to left side of the deque.
- */
- bool push_front( value_type const& val )
- {
- return push_node_front( alloc_node( val ));
- }
-
- /// Push front side using copy functor
- /**
- \p Func is a functor called to copy value \p data of type \p Type
- which may be differ from type \p T stored in the deque.
- The functor's interface is:
- \code
- struct myFunctor {
- void operator()(T& dest, Type const& data)
- {
- // Code to copy \p data to \p dest
- dest = data;
- }
- };
- \endcode
- You may use \p boost:ref construction to pass functor \p f by reference.
-
- <b>Requirements</b> The functor \p Func should not throw any exception.
- */
- template <typename Type, typename Func>
- bool push_front( Type const& val, Func f )
- {
- scoped_node_ptr p( alloc_node());
- unref(f)( p->m_value, val );
- if ( base_class::push_front( *p )) {
- p.release();
- return true;
- }
- return false;
- }
-
-# ifdef CDS_EMPLACE_SUPPORT
- /// Push front (left side) data of type \ref value_type constructed with <tt>std::forward<Args>(args)...</tt>
- /**
- Returns \p true if the operation successful, \p false otherwise.
-
- This function is available only for compiler that supports
- variadic template and move semantics
- */
- template <typename... Args>
- bool emplace_front( Args&&... args )
- {
- return push_node_front( alloc_node( std::forward<Args>(args)... ));
- }
-# endif
-
- /// Pops back side, no return value
- /**
- The function returns \p true if the deque has not been empty (in other words, an item has been popped),
- otherwise the function returns \p false.
- */
- bool pop_back()
- {
- return base_class::pop_back() != nullptr;
- }
-
- /// Pops back side a value using copy functor
- /**
- \p Func is a functor called to copy value popped to \p dest of type \p Type
- which may be differ from type \p T stored in the deque.
- The functor's interface is:
- \code
- struct myFunctor {
- void operator()(Type& dest, T const& data)
- {
- // Code to copy \p data to \p dest
- dest = data;
- }
- };
- \endcode
- You may use \p boost:ref construction to pass functor \p f by reference.
-
- <b>Requirements</b> The functor \p Func should not throw any exception.
- */
- template <typename Type, typename Func>
- bool pop_back( Type& dest, Func f )
- {
- typename base_class::pop_result res;
- if ( base_class::do_pop_back( res )) {
- unref(f)( dest, node_traits::to_value_ptr( res.pPopped )->m_value );
- base_class::dispose_result( res );
- return true;
- }
- return false;
- }
-
-
- /// Pops back side, store value popped into \p dest
- /**
- If deque is not empty, the function returns \p true, \p dest contains copy of
- value popped. The assignment operator for type \ref value_type is invoked.
- If deque is empty, the function returns \p false, \p dest is unchanged.
- */
- bool pop_back( value_type& dest )
- {
- typedef cds::details::trivial_assign<value_type, value_type> functor;
- return pop_back( dest, functor() );
- }
-
- /// Pops front side, no return value
- /**
- The function returns \p true if the deque has not been empty (in other words, an item has been popped),
- otherwise the function returns \p false.
- */
- bool pop_front()
- {
- return base_class::pop_front() != nullptr;
- }
-
- /// Pops front side a value using copy functor
- /**
- \p Func is a functor called to copy value popped to \p dest of type \p Type
- which may be differ from type \p T stored in the deque.
- The functor's interface is:
- \code
- struct myFunctor {
- void operator()(Type& dest, T const& data)
- {
- // Code to copy \p data to \p dest
- dest = data;
- }
- };
- \endcode
- You may use \p boost:ref construction to pass functor \p f by reference.
-
- <b>Requirements</b> The functor \p Func should not throw any exception.
- */
- template <typename Type, typename Func>
- bool pop_front( Type& dest, Func f )
- {
- typename base_class::pop_result res;
- if ( base_class::do_pop_front( res )) {
- unref(f)( dest, node_traits::to_value_ptr( res.pPopped )->m_value );
- base_class::dispose_result( res );
- return true;
- }
- return false;
- }
-
-
- /// Pops front side, store value popped into \p dest
- /**
- If deque is not empty, the function returns \p true, \p dest contains copy of
- value popped. The assignment operator for type \ref value_type is invoked.
- If deque is empty, the function returns \p false, \p dest is unchanged.
- */
- bool pop_front( value_type& dest )
- {
- typedef cds::details::trivial_assign<value_type, value_type> functor;
- return pop_front( dest, functor() );
- }
-
- /// Returns deque's item count
- /**
- The value returned depends on opt::item_counter option. For atomicity::empty_item_counter,
- this function always returns 0.
-
- <b>Warning</b>: even if you use real item counter and it returns 0, this fact does not mean that the deque
- is empty. To check deque emptyness use \ref empty() method.
- */
- size_t size() const
- {
- return base_class::size();
- }
-
- /// Checks if the dequeue is empty
- bool empty() const
- {
- return base_class::empty();
- }
-
- /// Clear the deque
- /**
- The function repeatedly calls \ref pop_back until it returns \p nullptr.
- */
- void clear()
- {
- return base_class::clear();
- }
-
- /// Returns reference to internal statistics
- const stat& statistics() const
- {
- return base_class::statistics();
- }
- };
-
-}} // namespace cds::container
-
-
-#endif // #ifndef __CDS_CONTAINER_MICHAEL_DEQUE_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef __CDS_INTRUSIVE_DEQUE_STAT_H
-#define __CDS_INTRUSIVE_DEQUE_STAT_H
-
-#include <cds/cxx11_atomic.h>
-
-namespace cds { namespace intrusive {
-
- /// Deque internal statistics. May be used for debugging or profiling
- /** @ingroup cds_intrusive_helper
- Template argument \p Counter defines type of counter.
- Default is cds::atomics::event_counter.
- You may use other counter type like as cds::atomics::item_counter,
- or even integral type, for example, \p int.
- */
- template <typename Counter = cds::atomicity::event_counter >
- struct deque_stat
- {
- typedef Counter counter_type ; ///< Counter type
-
- counter_type m_PushFrontCount ; ///< push front event count
- counter_type m_PushBackCount ; ///< push back event count
- counter_type m_PopFrontCount ; ///< pop front event count
- counter_type m_PopBackCount ; ///< pop back event count
- counter_type m_PopEmptyCount ; ///< pop from empty deque event count
- counter_type m_PushFrontContentionCount ; ///< \p push_front contention count
- counter_type m_PushBackContentionCount ; ///< \p push_back contention count
- counter_type m_PopFrontContentionCount ; ///< \p pop_front contention count
- counter_type m_PopBackContentionCount ; ///< \p pop_back contention count
-
- /// Register \p push_front call
- void onPushFront() { ++m_PushFrontCount; }
-
- /// Register \p push_back call
- void onPushBack() { ++m_PushBackCount; }
-
- /// Register \p pop_front call
- void onPopFront() { ++m_PopFrontCount; }
-
- /// Register \p pop_back call
- void onPopBack() { ++m_PopBackCount; }
-
- /// Register popping from empty deque
- void onPopEmpty() { ++m_PopEmptyCount; }
-
- /// Register "\p push_front contention" event
- void onPushFrontContention() { ++m_PushFrontContentionCount; }
-
- /// Register "\p push_back contention" event
- void onPushBackContention() { ++m_PushBackContentionCount; }
-
- /// Register "\p pop_front contention" event
- void onPopFrontContention() { ++m_PopFrontContentionCount; }
-
- /// Register "\p pop_back contention" event
- void onPopBackContention() { ++m_PopBackContentionCount; }
- };
-
-
- /// Dummy deque statistics - no counting is performed. Support interface like \ref deque_stat
- /** @ingroup cds_intrusive_helper
- */
- struct deque_dummy_stat
- {
- //@cond
- void onPushFront() {}
- void onPushBack() {}
- void onPopFront() {}
- void onPopBack() {}
- void onPopEmpty() {}
- void onPushFrontContention() {}
- void onPushBackContention() {}
- void onPopFrontContention() {}
- void onPopBackContention() {}
- //@endcond
- };
-
-}} // namespace cds::intrusive
-
-
-#endif // #ifndef __CDS_INTRUSIVE_DEQUE_STAT_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef __CDS_INTRUSIVE_MICHAEL_DEQUE_H
-#define __CDS_INTRUSIVE_MICHAEL_DEQUE_H
-
-#include <type_traits>
-#include <cds/intrusive/michael_list_impl.h>
-#include <cds/intrusive/michael_set.h>
-#include <cds/intrusive/deque_stat.h>
-#include <cds/ref.h>
-#include <cds/details/aligned_type.h>
-#include <cds/gc/default_gc.h>
-
-namespace cds { namespace intrusive {
-
- //@cond
- struct michael_deque_tag;
- //@endcond
-
- /// MichaelDeque related definitions
- /** @ingroup cds_intrusive_helper
- */
- namespace michael_deque
- {
- /// Anchor contains left/right sibling items
- /**
- The anchor object is maintained by one CAS instruction.
- */
- struct anchor
- {
- unsigned int idxLeft ; ///< Left sibling index; the most-significant bit contains left-stable flag
- unsigned int idxRight ; ///< Right sibling index; the most-significant bit contains right-stable flag
-
-# ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
- //@cond
- anchor() CDS_NOEXCEPT_DEFAULTED = default;
- anchor( anchor const& ) CDS_NOEXCEPT_DEFAULTED = default;
- ~anchor() CDS_NOEXCEPT_DEFAULTED = default;
- anchor& operator=(anchor const&) CDS_NOEXCEPT_DEFAULTED = default;
-# if defined(CDS_MOVE_SEMANTICS_SUPPORT) && !defined(CDS_DISABLE_DEFAULT_MOVE_CTOR)
- anchor( anchor&&) CDS_NOEXCEPT_DEFAULTED = default;
- anchor& operator=(anchor&&) CDS_NOEXCEPT_DEFAULTED = default;
-# endif
- //@endcond
-# else
- /// Default ctor does not initialize left/right indices
- anchor() CDS_NOEXCEPT
- : idxLeft( 0 )
- , idxRight( 0 )
- {
- static_check();
- }
-
- anchor( anchor const& a) CDS_NOEXCEPT
- : idxLeft( a.idxLeft )
- , idxRight( a.idxRight )
- {
- static_check();
- }
-# endif
-
- /// Constructor sets \p left / \p right indices
- anchor( unsigned int left, unsigned int right ) CDS_NOEXCEPT
- : idxLeft( left )
- , idxRight( right )
- {
- static_check();
- }
-
- /// Anchor equal operator
- bool operator ==( anchor const& a) const CDS_NOEXCEPT
- {
- return idxLeft == a.idxLeft && idxRight == a.idxRight;
- }
-
- /// Anchor non-equal operator
- bool operator !=( anchor const& a) const CDS_NOEXCEPT
- {
- return !( *this == a );
- }
-
- private:
- //@cond
- static void static_check()
- {
- static_assert( sizeof(unsigned int) * 2 <= 8, "The index type must be no more than 32bit long" );
- static_assert( sizeof(anchor) <= 8, "The anchor type must be no more than 64bit long" );
- }
- //@endcond
- };
-
- /// Michael's deque node
- /**
- Template parameters:
- - GC - garbage collector
- - Tag - a tag used to distinguish between different implementation
- */
- template <class GC, typename Tag = opt::none>
- struct node: public michael_list::node< GC, michael_deque_tag >
- {
- typedef GC gc ; ///< Garbage collector
- typedef Tag tag ; ///< tag
-
- //@cond
- typedef michael_list::node< gc, michael_deque_tag > mapper_node_type;
- //@endcond
-
- typedef typename gc::template atomic_type< anchor > atomic_anchor ; ///< atomic reference to left/right node
-
- CDS_DATA_ALIGNMENT(8) atomic_anchor m_Links ; ///< Left/right sibling links
- unsigned int m_nIndex; ///< Item index
-
- //@cond
- node()
- {
- m_Links.store( anchor(0,0), atomics::memory_order_release );
- }
-
- explicit node( anchor const& a )
- : m_Links()
- , m_nIndex(0)
- {
- m_Links.store( a, atomics::memory_order_release );
- }
- //@endcond
- };
-
- //@cond
- struct default_hook {
- typedef cds::gc::default_gc gc;
- typedef opt::none tag;
- typedef unsigned int index_type;
- };
- //@endcond
-
- //@cond
- template < typename HookType, CDS_DECL_OPTIONS3>
- struct hook
- {
- typedef typename opt::make_options< default_hook, CDS_OPTIONS3>::type options;
- typedef typename options::gc gc;
- typedef typename options::tag tag;
- typedef typename options::index_type index_type;
-
- typedef node<gc, tag> node_type;
- typedef HookType hook_type;
- };
- //@endcond
-
-
- /// Base hook
- /**
- \p Options are:
- - opt::gc - garbage collector used.
- - opt::tag - tag
- - opt::index_type - integral index type
- */
- template < CDS_DECL_OPTIONS3 >
- struct base_hook: public hook< opt::base_hook_tag, CDS_OPTIONS3 >
- {};
-
- /// Member hook
- /**
- \p MemberOffset defines offset in bytes of \ref node member into your structure.
- Use \p offsetof macro to define \p MemberOffset
-
- \p Options are:
- - opt::gc - garbage collector used.
- - opt::tag - tag
- - opt::index_type - integral index type
- */
- template < size_t MemberOffset, CDS_DECL_OPTIONS3 >
- struct member_hook: public hook< opt::member_hook_tag, CDS_OPTIONS3 >
- {
- //@cond
- static const size_t c_nMemberOffset = MemberOffset;
- //@endcond
- };
-
- /// Traits hook
- /**
- \p NodeTraits defines type traits for node.
- See \ref node_traits for \p NodeTraits interface description
-
- \p Options are:
- - opt::gc - garbage collector used.
- - opt::tag - tag
- - opt::index_type - integral index type
- */
- template <typename NodeTraits, CDS_DECL_OPTIONS3 >
- struct traits_hook: public hook< opt::traits_hook_tag, CDS_OPTIONS3 >
- {
- //@cond
- typedef NodeTraits node_traits;
- //@endcond
- };
-
- /// Deque internal statistics. May be used for debugging or profiling
- /**
- Template argument \p Counter defines type of counter.
- Default is cds::atomics::event_counter.
- You may use other counter type like as cds::atomics::item_counter,
- or even integral type, for example, \p int.
-
- The class extends intrusive::deque_stat interface for MichaelDeque.
- */
- template <typename Counter = cds::atomicity::event_counter >
- struct stat: public cds::intrusive::deque_stat<Counter>
- {
- //@cond
- typedef cds::intrusive::deque_stat<Counter> base_class;
- typedef typename base_class::counter_type counter_type;
- //@endcond
-
- counter_type m_StabilizeFrontCount ; ///< stabilize left event count
- counter_type m_StabilizeBackCount ; ///< stabilize right event count
-
- /// Register "stabilize left" event
- void onStabilizeFront() { ++m_StabilizeFrontCount; }
-
- /// Register "stabilize right" event
- void onStabilizeBack() { ++m_StabilizeBackCount; }
- };
-
- /// Dummy deque statistics - no counting is performed. Support interface like \ref michael_deque::stat
- struct dummy_stat: public cds::intrusive::deque_dummy_stat
- {
- //@cond
- void onStabilizeFront() {}
- void onStabilizeBack() {}
- //@endcond
- };
-
- //@cond
- template < typename NodeType, opt::link_check_type LinkType>
- struct link_checker
- {
- typedef NodeType node_type;
-
- static void is_empty( const node_type * pNode )
- {
-# ifdef _DEBUG
- anchor a = pNode->m_Links.load(atomics::memory_order_relaxed);
- assert( a.idxLeft == 0 && a.idxRight == 0 );
-# endif
- }
- };
-
- template < typename NodeType>
- struct link_checker<NodeType, opt::never_check_link>
- {
- typedef NodeType node_type;
-
- static void is_empty( const node_type * /*pNode*/ )
- {}
- };
- //@endcond
- } // namespace michael_deque
-
- /// Michael's intrusive deque
- /** @ingroup cds_intrusive_deque
- Implementation of Michael's deque algorithm.
-
- \par Source:
- [2003] Maged Michael "CAS-based Lock-free Algorithm for Shared Deque"
-
- <b>Short description</b> (from Michael's paper)
-
- The deque is represented as a doubly-linked list. Each node in the list contains two link pointers,
- \p pRight and \p pLeft, and a data field. A shared variable, \p Anchor, holds the two anchor
- pointers to the leftmost and rightmost nodes in the list, if any, and a three-value
- status tag. Anchor must fit in a memory block that can be read and manipulated
- using CAS or LL/SC, atomically. Initially both anchor pointers have null values
- and the status tag holds the value stable, indicating an empty deque.
-
- The status tag serves to indicate if the deque is in an unstable state. When
- a process finds the deque in an unstable state, it must first attempt to take it
- to a stable state before attempting its own operation.
-
- The algorithm can use single-word CAS or LL/SC.
- In \p libcds implementation of the algorithm the node contains two
- 31bit link indices instead of pointers + one bit for status tag;
- this trick allows use 64bit CAS to manipulate \p Anchor. Internal mapper
- (based on MichaelHashSet intrusive container)
- reflects link indices to item pointers. The maximum number of item in
- the deque is limited by 2**31 that is practically unbounded.
-
- Template arguments:
- - \p GC - garbage collector type: gc::HP or gc::PTB. Note that gc::HRC is not supported
- - \p T - type to be stored in the queue, should be convertible to michael_deque::node
- - \p Options - options
-
- Type of node: \ref michael_deque::node
-
- \p Options are:
- - opt::hook - hook used. Possible values are: michael_deque::base_hook, michael_deque::member_hook, michael_deque::traits_hook.
- If the option is not specified, <tt>michael_deque::base_hook<></tt> is used.
- - opt::back_off - back-off strategy used. If the option is not specified, the cds::backoff::empty is used.
- - opt::disposer - the functor used for dispose removed items. Default is opt::v::empty_disposer. This option is used
- in \ref pop_front and \ref pop_back functions.
- - opt::link_checker - the type of node's link fields checking. Default is \ref opt::debug_check_link
- - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter (no item counting feature)
- - opt::stat - the type to gather internal statistics.
- Possible option value are: \ref michael_deque::stat, \ref michael_deque::dummy_stat, user-provided class that supports michael_deque::stat interface.
- Default is \ref michael_deque::dummy_stat.
- - opt::alignment - the alignment for internal deque 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).
- - opt::allocator - allocator using for internal memory mapper based on MichaelHashSet. Default is CDS_DEFAULT_ALLOCATOR.
- */
- template <typename GC, typename T, CDS_DECL_OPTIONS10>
- class MichaelDeque
- {
- //@cond
- struct default_options
- {
- typedef cds::backoff::empty back_off;
- typedef michael_deque::base_hook<> hook;
- typedef opt::v::empty_disposer disposer;
- typedef atomicity::empty_item_counter item_counter;
- typedef michael_deque::dummy_stat stat;
- typedef opt::v::relaxed_ordering memory_model;
- static const opt::link_check_type link_checker = opt::debug_check_link;
- enum { alignment = opt::cache_line_alignment };
- typedef CDS_DEFAULT_ALLOCATOR allocator;
- };
- //@endcond
-
- public:
- //@cond
- typedef typename opt::make_options<
- typename cds::opt::find_type_traits< default_options, CDS_OPTIONS10 >::type
- ,CDS_OPTIONS10
- >::type options;
- //@endcond
-
- private:
- //@cond
- typedef typename std::conditional<
- std::is_same<typename options::stat, cds::intrusive::deque_stat<> >::value
- ,michael_deque::stat<>
- ,typename std::conditional<
- std::is_same<typename options::stat, cds::intrusive::deque_dummy_stat>::value
- ,michael_deque::dummy_stat
- ,typename options::stat
- >::type
- >::type stat_type_;
- //@endcond
-
-
- public:
- typedef T value_type ; ///< type of value stored in the deque
- typedef typename options::hook hook ; ///< hook type
- typedef typename hook::node_type node_type ; ///< node type
- typedef typename options::disposer disposer ; ///< disposer used
- typedef typename get_node_traits< value_type, node_type, hook>::type node_traits ; ///< node traits
- typedef michael_deque::link_checker< node_type, options::link_checker > link_checker ; ///< link checker
-
- typedef GC gc ; ///< Garbage collector
- typedef typename options::back_off back_off ; ///< back-off strategy
- typedef typename options::item_counter item_counter ; ///< Item counting policy used
- typedef stat_type_ stat ; ///< Internal statistics policy used
- typedef typename options::memory_model memory_model; ///< Memory ordering. See cds::opt::memory_model option
- typedef typename options::allocator allocator_type ; ///< Allocator using for internal memory mapping
-
- typedef typename node_type::atomic_anchor atomic_anchor ; ///< Atomic anchor
-
- protected:
- //@cond
- class index_mapper
- {
- struct node_less_comparator
- {
- bool operator ()( value_type const & n1, value_type const& n2) const
- {
- return node_traits::to_node_ptr(n1)->m_nIndex < node_traits::to_node_ptr(n2)->m_nIndex;
- }
- bool operator ()( unsigned int i, value_type const& n2) const
- {
- return i < node_traits::to_node_ptr(n2)->m_nIndex;
- }
- bool operator ()( value_type const & n1, unsigned int i) const
- {
- return node_traits::to_node_ptr(n1)->m_nIndex < i;
- }
- };
-
- struct internal_disposer
- {
- void operator()( value_type * p )
- {
- assert( p != nullptr );
-
- MichaelDeque::clear_links( node_traits::to_node_ptr(p) );
- disposer()( p );
- }
- };
-
- struct mapper_node_traits
- {
- typedef typename node_type::mapper_node_type mapper_node_type;
-
- static mapper_node_type * to_node_ptr( value_type& v )
- {
- return static_cast<mapper_node_type *>( node_traits::to_node_ptr(v) );
- }
-
- static mapper_node_type * to_node_ptr( value_type * v )
- {
- return static_cast<mapper_node_type *>( node_traits::to_node_ptr(v) );
- }
-
- static mapper_node_type const * to_node_ptr( value_type const& v )
- {
- return static_cast<mapper_node_type const *>( node_traits::to_node_ptr(v) );
- }
-
- static mapper_node_type const * to_node_ptr( value_type const * v )
- {
- return static_cast<mapper_node_type const *>( node_traits::to_node_ptr(v) );
- }
-
- static value_type * to_value_ptr( mapper_node_type& n )
- {
- return node_traits::to_value_ptr( static_cast<node_type&>(n));
- }
-
- static value_type * to_value_ptr( mapper_node_type * n )
- {
- return node_traits::to_value_ptr( static_cast<node_type *>(n));
- }
-
- static const value_type * to_value_ptr( mapper_node_type const& n )
- {
- return node_traits::to_value_ptr( static_cast<node_type const&>(n));
- }
-
- static const value_type * to_value_ptr( mapper_node_type const * n )
- {
- return node_traits::to_value_ptr( static_cast<node_type const *>(n));
- }
- };
-
- typedef MichaelList< gc, value_type,
- typename michael_list::make_traits<
- opt::hook< michael_list::traits_hook<
- mapper_node_traits
- ,cds::opt::gc< gc >
- ,cds::opt::tag<michael_deque_tag> >
- >
- ,opt::less< node_less_comparator >
- ,opt::back_off< back_off >
- ,opt::disposer< internal_disposer >
- ,opt::memory_model< memory_model >
- >::type
- > mapper_ordered_list;
-
- struct mapper_hash {
- size_t operator()( value_type const& v ) const
- {
- return cds::opt::v::hash<unsigned int>()( node_traits::to_node_ptr(v)->m_nIndex );
- }
- size_t operator()( unsigned int i ) const
- {
- return cds::opt::v::hash<unsigned int>()(i);
- }
- };
-
- typedef MichaelHashSet< gc, mapper_ordered_list,
- typename michael_set::make_traits<
- opt::hash< mapper_hash >
- ,opt::allocator< allocator_type >
- >::type
- > mapper_type;
-
-# if !(defined(CDS_CXX11_LAMBDA_SUPPORT) && !((CDS_COMPILER == CDS_COMPILER_MSVC || CDS_COMPILER == CDS_COMPILER_INTEL) && _MSC_VER < 1700))
- struct at_functor {
- node_type * pNode;
-
- at_functor()
- : pNode( nullptr )
- {}
-
- void operator()( value_type& v, unsigned int nIdx )
- {
- pNode = node_traits::to_node_ptr(v);
- assert( pNode->m_nIndex == nIdx );
- }
- };
-# endif
-
- mapper_type m_set;
- atomics::atomic<unsigned int> m_nLastIndex;
-
- public:
-
- index_mapper( size_t nEstimatedItemCount, size_t nLoadFactor )
- : m_set( nEstimatedItemCount, nLoadFactor )
- , m_nLastIndex(1)
- {}
-
- unsigned int map( value_type& v )
- {
- while ( true ) {
- node_type * pNode = node_traits::to_node_ptr( v );
- pNode->m_nIndex = m_nLastIndex.fetch_add( 1, memory_model::memory_order_relaxed );
- if ( pNode->m_nIndex && m_set.insert( v ))
- return pNode->m_nIndex;
- }
- }
-
- bool unmap( unsigned int nIdx )
- {
- return m_set.erase( nIdx );
- }
-
- node_type * at( unsigned int nIdx )
- {
-# if defined(CDS_CXX11_LAMBDA_SUPPORT) && !((CDS_COMPILER == CDS_COMPILER_MSVC ||CDS_COMPILER == CDS_COMPILER_INTEL) && _MSC_VER < 1700)
- // MS VC++2010 bug: error C2955: 'cds::intrusive::node_traits' : use of class template requires template argument list
- // see declaration of 'cds::intrusive::node_traits'
- node_type * pNode = nullptr;
- if ( m_set.find( nIdx,
- [&pNode](value_type& v, unsigned int nIdx) {
- pNode = node_traits::to_node_ptr(v);
- assert( pNode->m_nIndex == nIdx );
- })
- )
- return pNode;
-# else
- at_functor f;
- if ( m_set.find( nIdx, cds::ref(f) ))
- return f.pNode;
-# endif
- return nullptr;
- }
- };
- //@endcond
- public:
-
- /// Rebind template arguments
- template <typename GC2, typename T2, CDS_DECL_OTHER_OPTIONS10>
- struct rebind {
- typedef MichaelDeque< GC2, T2, CDS_OTHER_OPTIONS10> other ; ///< Rebinding result
- };
-
- protected:
- typename cds::opt::details::alignment_setter< atomic_anchor, options::alignment >::type m_Anchor ; ///< Left/right heads
- typename cds::opt::details::alignment_setter< index_mapper, options::alignment >::type m_Mapper ; ///< Memory mapper
-
- item_counter m_ItemCounter ; ///< item counter
- stat m_Stat ; ///< Internal statistics
-
- //@cond
- static const unsigned int c_nIndexMask = ((unsigned int)(0 - 1)) >> 1;
- static const unsigned int c_nFlagMask = ((unsigned int)(1)) << (sizeof(unsigned int) * 8 - 1);
- static const unsigned int c_nEmptyIndex = 0;
- //@endcond
-
- private:
- //@cond
- typedef michael_deque::anchor CDS_TYPE_ALIGNMENT(8) anchor_type;
- typedef intrusive::node_to_value<MichaelDeque> node_to_value;
-
- static void clear_links( node_type * pNode )
- {
- pNode->m_Links.store( anchor_type(), memory_model::memory_order_release );
- }
-
- enum anchor_status {
- Stable,
- RPush,
- LPush
- };
-
- static anchor_status status( anchor_type const& a )
- {
- if ( a.idxLeft & c_nFlagMask )
- return LPush;
- if ( a.idxRight & c_nFlagMask )
- return RPush;
- return Stable;
- }
-
- static unsigned int index( unsigned int i )
- {
- return i & c_nIndexMask;
- }
-
- void stabilize( anchor_type& a )
- {
- switch ( status(a)) {
- case LPush:
- stabilize_front(a);
- break;
- case RPush:
- stabilize_back(a);
- break;
- default:
- break;
- }
- }
-
- void stabilize_front( anchor_type& a )
- {
- m_Stat.onStabilizeFront();
-
- typename gc::template GuardArray<3> guards;
- node_type * pLeft;
- node_type * pRight;
- unsigned int const idxLeft = index( a.idxLeft );
- unsigned int const idxRight = index( a.idxRight );
-
- guards.assign( 0, node_traits::to_value_ptr( pLeft = m_Mapper.at( idxLeft )) );
- guards.assign( 1, node_traits::to_value_ptr( pRight = m_Mapper.at( idxRight )) );
- if ( m_Anchor.load( memory_model::memory_order_acquire ) != a )
- return;
-
- unsigned int idxPrev = index( pLeft->m_Links.load(memory_model::memory_order_relaxed ).idxRight );
- node_type * pPrev;
- guards.assign( 2, node_traits::to_value_ptr( pPrev = m_Mapper.at( idxPrev )) );
- if ( m_Anchor.load( memory_model::memory_order_acquire ) != a )
- return;
-
- anchor_type prevLinks( pPrev->m_Links.load( memory_model::memory_order_acquire ));
- if ( index( prevLinks.idxLeft ) != idxLeft ) {
- if ( m_Anchor.load( memory_model::memory_order_acquire ) != a )
- return;
-
- if ( !pPrev->m_Links.compare_exchange_strong( prevLinks, anchor_type( idxLeft, prevLinks.idxRight ), memory_model::memory_order_release, memory_model::memory_order_relaxed ))
- return;
- }
-
- // clear RPush/LPush flags
- m_Anchor.compare_exchange_weak( a, anchor_type(idxLeft, idxRight), memory_model::memory_order_release, memory_model::memory_order_relaxed );
- }
-
- void stabilize_back( anchor_type& a )
- {
- m_Stat.onStabilizeBack();
-
- typename gc::template GuardArray<3> guards;
- node_type * pLeft;
- node_type * pRight;
- unsigned int const idxLeft = index( a.idxLeft );
- unsigned int const idxRight = index( a.idxRight );
-
- guards.assign( 0, node_traits::to_value_ptr( pLeft = m_Mapper.at( idxLeft )) );
- guards.assign( 1, node_traits::to_value_ptr( pRight = m_Mapper.at( idxRight )) );
- if ( m_Anchor.load( memory_model::memory_order_acquire ) != a )
- return;
-
- unsigned int idxPrev = index( pRight->m_Links.load(memory_model::memory_order_relaxed ).idxLeft );
- node_type * pPrev;
- guards.assign( 2, node_traits::to_value_ptr( pPrev = m_Mapper.at( idxPrev )) );
- if ( m_Anchor.load( memory_model::memory_order_acquire ) != a )
- return;
-
- anchor_type prevLinks( pPrev->m_Links.load( memory_model::memory_order_acquire ));
- if ( index( prevLinks.idxRight ) != idxRight ) {
- if ( m_Anchor.load( memory_model::memory_order_acquire ) != a )
- return;
-
- if ( !pPrev->m_Links.compare_exchange_strong( prevLinks, anchor_type( prevLinks.idxLeft, idxRight ), memory_model::memory_order_release, memory_model::memory_order_relaxed ))
- return;
- }
-
- // clear RPush/LPush flags
- m_Anchor.compare_exchange_weak( a, anchor_type(idxLeft, idxRight), memory_model::memory_order_release, memory_model::memory_order_relaxed );
- }
-
- //@endcond
-
- protected:
- //@cond
- struct pop_result {
- value_type * pPopped;
- unsigned int nIdxPopped;
- typename gc::template GuardArray<2> guards;
- };
-
- void dispose_result( pop_result& res )
- {
- m_Mapper.unmap( res.nIdxPopped );
- }
-
- bool do_pop_back( pop_result& res )
- {
- back_off bkoff;
- anchor_type a;
-
- while ( true ) {
- a = m_Anchor.load( memory_model::memory_order_acquire );
-
- if ( a.idxRight == c_nEmptyIndex ) {
- m_Stat.onPopEmpty();
- return false;
- }
-
- if ( a.idxLeft == a.idxRight ) {
- if ( m_Anchor.compare_exchange_weak( a, anchor_type( c_nEmptyIndex, c_nEmptyIndex ), memory_model::memory_order_release, memory_model::memory_order_relaxed ))
- break;
- bkoff();
- }
- else if ( status( a ) == Stable ) {
- unsigned int idxLeft = index( a.idxLeft );
- unsigned int idxRight = index( a.idxRight );
- node_type * pLeft;
- res.guards.assign( 0, node_traits::to_value_ptr( pLeft = m_Mapper.at( idxLeft )) );
- node_type * pRight;
- res.guards.assign( 1, node_traits::to_value_ptr( pRight = m_Mapper.at( idxRight )) );
-
- if ( m_Anchor.load( memory_model::memory_order_acquire ) != a ) {
- m_Stat.onPopBackContention();
- continue;
- }
-
- unsigned int nPrev = pRight->m_Links.load( memory_model::memory_order_acquire ).idxLeft;
- if ( m_Anchor.compare_exchange_weak( a, anchor_type( a.idxLeft, nPrev ), memory_model::memory_order_release, memory_model::memory_order_relaxed ) )
- break;
- bkoff();
- m_Stat.onPopBackContention();
- }
- else
- stabilize( a );
- }
-
- res.nIdxPopped = a.idxRight;
- res.pPopped = node_traits::to_value_ptr( m_Mapper.at( a.idxRight ));
-
- --m_ItemCounter;
- m_Stat.onPopBack();
-
- return true;
- }
-
- bool do_pop_front( pop_result& res )
- {
- back_off bkoff;
- anchor_type a;
-
- while ( true ) {
- a = m_Anchor.load( memory_model::memory_order_acquire );
-
- if ( a.idxLeft == c_nEmptyIndex ) {
- m_Stat.onPopEmpty();
- return false;
- }
-
- if ( a.idxLeft == a.idxRight ) {
- if ( m_Anchor.compare_exchange_weak( a, anchor_type( c_nEmptyIndex, c_nEmptyIndex ), memory_model::memory_order_release, memory_model::memory_order_relaxed ))
- break;
- bkoff();
- }
- else if ( status( a ) == Stable ) {
- unsigned int idxLeft = index( a.idxLeft );
- unsigned int idxRight = index( a.idxRight );
- node_type * pLeft;
- res.guards.assign( 0, node_traits::to_value_ptr( pLeft = m_Mapper.at( idxLeft )) );
- node_type * pRight;
- res.guards.assign( 1, node_traits::to_value_ptr( pRight = m_Mapper.at( idxRight )) );
-
- if ( m_Anchor.load( memory_model::memory_order_acquire ) != a ) {
- m_Stat.onPopFrontContention();
- continue;
- }
-
- unsigned int nPrev = pLeft->m_Links.load( memory_model::memory_order_acquire ).idxRight;
- if ( m_Anchor.compare_exchange_weak( a, anchor_type( nPrev, a.idxRight ), memory_model::memory_order_release, memory_model::memory_order_relaxed ) )
- break;
- bkoff();
- m_Stat.onPopFrontContention();
- }
- else
- stabilize( a );
- }
-
- res.nIdxPopped = a.idxLeft;
- res.pPopped = node_traits::to_value_ptr( m_Mapper.at( a.idxLeft ));
-
- --m_ItemCounter;
- m_Stat.onPopFront();
-
- return true;
- }
-
- //@endcond
-
- public:
- /// Default constructor
- /**
- Initializes the deque object with up to <tt>2**16 - 2</tt> items
- */
- MichaelDeque()
- :m_Anchor()
- ,m_Mapper( 4096, 4 )
- {
- m_Anchor.store( anchor_type( c_nEmptyIndex, c_nEmptyIndex ), atomics::memory_order_release );
-
- // GC and node_type::gc must be the same
- static_assert(( std::is_same<gc, typename node_type::gc>::value ), "GC and node_type::gc must be the same");
-
- // cds::gc::HRC is not allowed
- static_assert(( !std::is_same<gc, cds::gc::HRC>::value ), "cds::gc::HRC is not allowed here");
- }
-
- /// Constructor
- /**
- Initializes the deque object with estimated item count \p nMaxItemCount.
- \p nLoadFactor is a parameter of internal memory mapper based on MichaelHashSet;
- see MichaelHashSet ctor for details
- */
- MichaelDeque( unsigned int nMaxItemCount, unsigned int nLoadFactor = 4 )
- :m_Anchor()
- ,m_Mapper( nMaxItemCount, nLoadFactor )
- {
- m_Anchor.store( anchor_type( c_nEmptyIndex, c_nEmptyIndex ), atomics::memory_order_release );
-
- // GC and node_type::gc must be the same
- static_assert(( std::is_same<gc, typename node_type::gc>::value ), "GC and node_type::gc must be the same");
-
- // cds::gc::HRC is not allowed
- static_assert(( !std::is_same<gc, cds::gc::HRC>::value ), "cds::gc::HRC is not allowed here");
- }
-
- /// Destructor clears the deque
- ~MichaelDeque()
- {
- clear();
- }
-
- public:
- /// Push back (right) side
- /**
- Push new item \p val to right side of the deque.
- */
- bool push_back( value_type& val )
- {
- back_off bkoff;
-
- node_type * pNode = node_traits::to_node_ptr( val );
- link_checker::is_empty( pNode );
-
- unsigned int nIdx = m_Mapper.map( val );
- if ( nIdx == c_nEmptyIndex )
- return false;
-
- while ( true ) {
- anchor_type a = m_Anchor.load( memory_model::memory_order_acquire );
- if ( a.idxRight == c_nEmptyIndex ) {
- if ( m_Anchor.compare_exchange_weak( a, anchor_type( nIdx, nIdx ), memory_model::memory_order_release, memory_model::memory_order_relaxed ))
- break;
- bkoff();
- m_Stat.onPushBackContention();
- }
- else if ( status(a) == Stable ) {
- pNode->m_Links.store( anchor_type( a.idxRight, c_nEmptyIndex ), memory_model::memory_order_release );
- anchor_type aNew( a.idxLeft, nIdx | c_nFlagMask );
- if ( m_Anchor.compare_exchange_weak( a, aNew, memory_model::memory_order_release, memory_model::memory_order_relaxed) ) {
- stabilize_back( aNew );
- break;
- }
- bkoff();
- m_Stat.onPushBackContention();
- }
- else
- stabilize( a );
- }
-
- ++m_ItemCounter;
- m_Stat.onPushBack();
- return true;
- }
-
- /// Push front (left) side
- /**
- Push new item \p val to left side of the deque.
- */
- bool push_front( value_type& val )
- {
- back_off bkoff;
- node_type * pNode = node_traits::to_node_ptr( val );
- link_checker::is_empty( pNode );
-
- unsigned int nIdx = m_Mapper.map( val );
- if ( nIdx == c_nEmptyIndex )
- return false;
-
- while ( true ) {
- anchor_type a = m_Anchor.load( memory_model::memory_order_acquire );
- if ( a.idxLeft == c_nEmptyIndex ) {
- if ( m_Anchor.compare_exchange_weak( a, anchor_type( nIdx, nIdx ), memory_model::memory_order_release, memory_model::memory_order_relaxed ))
- break;
- bkoff();
- m_Stat.onPushFrontContention();
- }
- else if ( status(a) == Stable ) {
- pNode->m_Links.store( anchor_type( c_nEmptyIndex, a.idxLeft ), memory_model::memory_order_release );
- anchor_type aNew( nIdx | c_nFlagMask, a.idxRight );
- if ( m_Anchor.compare_exchange_weak( a, aNew, memory_model::memory_order_release, memory_model::memory_order_relaxed )) {
- stabilize_front( aNew );
- break;
- }
- bkoff();
- m_Stat.onPushFrontContention();
- }
- else
- stabilize( a );
- }
-
- ++m_ItemCounter;
- m_Stat.onPushFront();
- return true;
- }
-
- /// Pop back
- /**
- Pops rightmost item from the deque. If the deque is empty then returns \p nullptr.
-
- For popped object the disposer specified in \p Options template parameters is called.
- */
- value_type * pop_back()
- {
- pop_result res;
- if ( do_pop_back( res )) {
- dispose_result( res );
- return res.pPopped;
- }
-
- return nullptr;
- }
-
- /// Pop front
- /**
- Pops leftmost item from the deque. If the deque is empty then returns \p nullptr.
-
- For popped object the disposer specified in \p Options template parameters is called.
- */
- value_type * pop_front()
- {
- pop_result res;
- if ( do_pop_front( res )) {
- dispose_result( res );
- return res.pPopped;
- }
-
- return nullptr;
- }
-
- /// Returns deque's item count
- /**
- The value returned depends on opt::item_counter option. For atomicity::empty_item_counter,
- this function always returns 0.
-
- <b>Warning</b>: even if you use real item counter and it returns 0, this fact does not mean that the deque
- is empty. To check deque emptyness use \ref empty() method.
- */
- size_t size() const
- {
- return m_ItemCounter.value();
- }
-
- /// Checks if the dequeue is empty
- bool empty() const
- {
- anchor_type a = m_Anchor.load( memory_model::memory_order_relaxed );
- return a.idxLeft == c_nEmptyIndex && a.idxRight == c_nEmptyIndex;
- }
-
- /// Clear the deque
- /**
- The function repeatedly calls \ref pop_back until it returns \p nullptr.
- The disposer defined in template \p Options is called for each item
- that can be safely disposed.
- */
- void clear()
- {
- while ( pop_back() != nullptr );
- }
-
- /// Returns reference to internal statistics
- const stat& statistics() const
- {
- return m_Stat;
- }
- };
-
-
-}} // namespace cds::intrusive
-
-
-#endif // #ifndef __CDS_INTRUSIVE_MICHAEL_DEQUE_H
Microsoft Visual Studio Solution File, Format Version 12.00\r
-# Visual Studio 2013\r
-VisualStudioVersion = 12.0.21005.1\r
+# Visual Studio Express 2013 for Windows Desktop\r
+VisualStudioVersion = 12.0.30723.0\r
MinimumVisualStudioVersion = 10.0.40219.1\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cds", "cds.vcxproj", "{408FE9BC-44F0-4E6A-89FA-D6F952584239}"\r
EndProject\r
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unit-test", "unit-test", "{B30CA283-1796-4763-92C3-2E4848D443F7}"\r
+ ProjectSection(SolutionItems) = preProject\r
+ ..\..\..\tests\unit\print_cuckoo_stat.h = ..\..\..\tests\unit\print_cuckoo_stat.h\r
+ ..\..\..\tests\unit\print_ellenbintree_stat.h = ..\..\..\tests\unit\print_ellenbintree_stat.h\r
+ ..\..\..\tests\unit\print_mspriorityqueue_stat.h = ..\..\..\tests\unit\print_mspriorityqueue_stat.h\r
+ ..\..\..\tests\unit\print_segmentedqueue_stat.h = ..\..\..\tests\unit\print_segmentedqueue_stat.h\r
+ ..\..\..\tests\unit\print_skip_list_stat.h = ..\..\..\tests\unit\print_skip_list_stat.h\r
+ EndProjectSection\r
EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unit-prerequisites", "unit-prerequisites.vcxproj", "{61179F2F-07E1-490D-B64D-D85A90B6EF81}"\r
ProjectSection(ProjectDependencies) = postProject\r
{77350FDC-9E51-438B-9A8F-D2FEA11D46B2} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
{6C15AF8A-4A99-49F9-BCF0-1BF36771099A} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
{E29DE1F7-AE8D-4AE6-98B1-147E5103D974} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
- {6BB7A27F-FC59-4267-B6FA-D034176D1459} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
- {A64449B7-90FB-4E2B-A686-9EFC0E298644} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
- {20B6C380-E96A-4CFF-BC17-D88AAE581919} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
{CD0BC7FC-9BFF-40B0-8E66-99D244A8A026} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
{282E9A9A-386A-40FB-A483-994BACE24830} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
{C5E76975-B87B-4B9E-8596-B01DDA683FCA} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
{EFCBBADE-2CF4-4E2B-ADB2-98C8D139E805} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
+ {6BB7A27F-FC59-4267-B6FA-D034176D1459} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
+ {A64449B7-90FB-4E2B-A686-9EFC0E298644} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
+ {3C598F96-FB84-4D42-9B43-F697F53B0221} = {6BB7A27F-FC59-4267-B6FA-D034176D1459}\r
+ {BA2A9239-0299-4069-BB0E-16DACE87ADE0} = {6BB7A27F-FC59-4267-B6FA-D034176D1459}\r
+ {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4} = {6BB7A27F-FC59-4267-B6FA-D034176D1459}\r
+ {AF7B2253-2E6D-4992-94D9-4B3699C54929} = {A64449B7-90FB-4E2B-A686-9EFC0E298644}\r
+ {BA23811C-D4CB-4836-B2F3-6791BD6FFCD1} = {A64449B7-90FB-4E2B-A686-9EFC0E298644}\r
{90192F7D-5850-41DD-AE89-62D26B387162} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
{33664E63-8D24-4FF4-A744-9782EB711509} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
{E5E9DB4A-7816-45D4-A116-6BBBA0EE8EE7} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
{E3F2927A-6ED6-4B18-BDE6-B3B760E1AF18} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
{A38E5597-6916-4480-A343-C9846EF544E4} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
{6F834EAD-7B94-4979-A0F1-A662E3D30145} = {B8C24D26-A3BF-4DA6-B64C-142CBA4BFE75}\r
- {3C598F96-FB84-4D42-9B43-F697F53B0221} = {6BB7A27F-FC59-4267-B6FA-D034176D1459}\r
- {BA2A9239-0299-4069-BB0E-16DACE87ADE0} = {6BB7A27F-FC59-4267-B6FA-D034176D1459}\r
- {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4} = {6BB7A27F-FC59-4267-B6FA-D034176D1459}\r
- {AF7B2253-2E6D-4992-94D9-4B3699C54929} = {A64449B7-90FB-4E2B-A686-9EFC0E298644}\r
- {BA23811C-D4CB-4836-B2F3-6791BD6FFCD1} = {A64449B7-90FB-4E2B-A686-9EFC0E298644}\r
+ {20B6C380-E96A-4CFF-BC17-D88AAE581919} = {B30CA283-1796-4763-92C3-2E4848D443F7}\r
EndGlobalSection\r
GlobalSection(DPCodeReviewSolutionGUID) = preSolution\r
DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000}\r
<ClInclude Include="..\..\..\cds\container\ellen_bintree_set_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\lazy_kvlist_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\lazy_list_rcu.h" />\r
- <ClInclude Include="..\..\..\cds\container\michael_deque.h" />\r
<ClInclude Include="..\..\..\cds\container\michael_kvlist_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\michael_list_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\michael_map_rcu.h" />\r
<ClInclude Include="..\..\..\cds\gc\ptb_impl.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\basket_queue.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\cuckoo_set.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\deque_stat.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\dummy_node_holder.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\ellen_bintree_base.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\ellen_bintree_hp.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\ellen_bintree_ptb.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\ellen_bintree_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\lazy_list_rcu.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\michael_deque.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\michael_list_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\michael_set_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\mspriority_queue.h" />\r
<ClInclude Include="..\..\..\cds\compiler\clang\defs.h">\r
<Filter>Header Files\cds\compiler\clang</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\michael_deque.h">\r
- <Filter>Header Files\cds\intrusive</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\cds\memory\mapper.h">\r
<Filter>Header Files\cds\memory</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\michael_deque.h">\r
- <Filter>Header Files\cds\container</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\cds\intrusive\basket_queue.h">\r
<Filter>Header Files\cds\intrusive</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\cds\container\basket_queue.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\deque_stat.h">\r
- <Filter>Header Files\cds\intrusive</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\cds\intrusive\cuckoo_set.h">\r
<Filter>Header Files\cds\intrusive</Filter>\r
</ClInclude>\r
<TargetMachine>MachineX64</TargetMachine>\r
</Link>\r
</ItemDefinitionGroup>\r
- <ItemGroup>\r
- <ClInclude Include="..\..\..\tests\test-hdr\deque\hdr_deque.h" />\r
- <ClInclude Include="..\..\..\tests\test-hdr\deque\hdr_intrusive_deque.h" />\r
- </ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\..\..\tests\test-hdr\deque\hdr_fcdeque.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\deque\hdr_intrusive_michael_deque_hp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\deque\hdr_intrusive_michael_deque_ptb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\deque\hdr_michael_deque_hp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\deque\hdr_michael_deque_ptb.cpp" />\r
</ItemGroup>\r
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
<ImportGroup Label="ExtensionTargets">\r
<ClInclude Include="..\..\..\tests\cppunit\file_reporter.h" />\r
<ClInclude Include="..\..\..\tests\unit\ellen_bintree_update_desc_pool.h" />\r
<ClInclude Include="..\..\..\tests\unit\michael_alloc.h" />\r
- <ClInclude Include="..\..\..\tests\unit\print_cuckoo_stat.h" />\r
- <ClInclude Include="..\..\..\tests\unit\print_deque_stat.h" />\r
<ClInclude Include="..\..\..\tests\cppunit\test_beans.h" />\r
<ClInclude Include="..\..\..\tests\cppunit\thread.h" />\r
- <ClInclude Include="..\..\..\tests\unit\print_ellenbintree_stat.h" />\r
- <ClInclude Include="..\..\..\tests\unit\print_mspriorityqueue_stat.h" />\r
- <ClInclude Include="..\..\..\tests\unit\print_segmentedqueue_stat.h" />\r
- <ClInclude Include="..\..\..\tests\unit\print_skip_list_stat.h" />\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\ellen_bintree_update_desc_pool.cpp" />\r
+++ /dev/null
-//$$CDS-header$$
-
-#include "cppunit/cppunit_proxy.h"
-#include "cppunit/test_beans.h"
-
-namespace deque {
-
- class DequeHeaderTest: public CppUnitMini::TestCase
- {
- public:
- struct value_type {
- int nVal;
-
- value_type()
- {}
- value_type( int i )
- : nVal(i)
- {}
- };
-
- struct assign_functor
- {
- template <typename T>
- void operator()( value_type& dest, T i ) const
- {
- dest.nVal = i;
- }
- };
-
- struct pop_functor
- {
- template <typename T>
- void operator()( T& dest, value_type const& v )
- {
- dest = v.nVal;
- }
- };
-
- static void assign_func( value_type& dest, int i )
- {
- dest.nVal = i;
- }
- static void pop_func( int& dest, value_type const& v )
- {
- dest = v.nVal;
- }
-
- template <class Deque>
- void test()
- {
- test_beans::check_item_counter<typename Deque::item_counter> check_ic;
-
- Deque q;
- value_type v;
- int i;
-
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
- // push_right/pop_right
- CPPUNIT_ASSERT( q.push_back( value_type(5) ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.push_back( 10, assign_functor() )) ; // functor
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.push_back( 20, assign_func )) ; // function
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
-
- CPPUNIT_ASSERT( q.pop_back(v) );
- CPPUNIT_ASSERT( v.nVal == 20 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_back( i, pop_functor()) );
- CPPUNIT_ASSERT( i == 10 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.pop_back(i, pop_func) );
- CPPUNIT_ASSERT( i == 5 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
- v.nVal = -1;
- CPPUNIT_ASSERT( !q.pop_back(v) );
- CPPUNIT_ASSERT( v.nVal == -1 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
-#ifdef CDS_EMPLACE_SUPPORT
- CPPUNIT_ASSERT( q.emplace_back( 157 ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.emplace_back( 158 ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_back(i, pop_func) );
- CPPUNIT_ASSERT( i == 158 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.pop_back(i, pop_functor()) );
- CPPUNIT_ASSERT( i == 157 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-#endif
-
-#ifdef CDS_CXX11_LAMBDA_SUPPORT
- CPPUNIT_ASSERT( q.push_back( value_type(511), [](value_type& dest, value_type const& i){ dest.nVal = i.nVal * 2; } ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.push_back( 512, [](value_type& dest, int i){ dest.nVal = i; } ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_back( i, []( int& dest, value_type const& v){ dest = v.nVal; } ) );
- CPPUNIT_ASSERT( i == 512 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- v.nVal = i = 0;
- CPPUNIT_ASSERT( q.pop_back( i, [&v]( int& dest, value_type const& val){ dest = -val.nVal; v.nVal = val.nVal; }) );
- CPPUNIT_ASSERT( i == -511 * 2 );
- CPPUNIT_ASSERT( v.nVal == 511 * 2);
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-#endif
-
- // push_right/pop_left
- CPPUNIT_ASSERT( q.push_back( value_type(5) ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.push_back( 10, assign_functor() )) ; // functor
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.push_back( 20, assign_func )) ; // function
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
-
- CPPUNIT_ASSERT( q.pop_front(v) );
- CPPUNIT_ASSERT( v.nVal == 5 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_front(i, pop_functor() ) );
- CPPUNIT_ASSERT( i == 10 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.pop_front( i, pop_func ) );
- CPPUNIT_ASSERT( i == 20 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
- v.nVal = -1;
- CPPUNIT_ASSERT( !q.pop_back(v) );
- CPPUNIT_ASSERT( v.nVal == -1 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
-#ifdef CDS_EMPLACE_SUPPORT
- CPPUNIT_ASSERT( q.emplace_back( 157 ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.emplace_back( 158 ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_front(i, pop_func) );
- CPPUNIT_ASSERT( i == 157 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.pop_front(i, pop_functor()) );
- CPPUNIT_ASSERT( i == 158 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-#endif
-
-#ifdef CDS_CXX11_LAMBDA_SUPPORT
- CPPUNIT_ASSERT( q.push_back( value_type(511), [](value_type& dest, value_type const& i){ dest.nVal = i.nVal * 2; } ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.push_back( 512, [](value_type& dest, int i){ dest.nVal = i; } ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_front( i, []( int& dest, value_type const& v){ dest = v.nVal; } ) );
- CPPUNIT_ASSERT( i == 511 * 2 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- v.nVal = i = 0;
- CPPUNIT_ASSERT( q.pop_front( i, [&v]( int& dest, value_type const& val){ dest = -val.nVal; v.nVal = val.nVal; }) );
- CPPUNIT_ASSERT( i == -512 );
- CPPUNIT_ASSERT( v.nVal == 512);
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-#endif
-
-
- // push_left/pop_left
- CPPUNIT_ASSERT( q.push_front( value_type(5) ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.push_front( 10, assign_functor() )) ; // functor
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.push_front( 20, assign_func )) ; // function
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
-
- CPPUNIT_ASSERT( q.pop_front(v) );
- CPPUNIT_ASSERT( v.nVal == 20 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_front(v) );
- CPPUNIT_ASSERT( v.nVal == 10 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.pop_front(v) );
- CPPUNIT_ASSERT( v.nVal == 5 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
-#ifdef CDS_EMPLACE_SUPPORT
- CPPUNIT_ASSERT( q.emplace_front( 157 ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.emplace_front( 158 ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_front(i, pop_func) );
- CPPUNIT_ASSERT( i == 158 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.pop_front(i, pop_functor()) );
- CPPUNIT_ASSERT( i == 157 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-#endif
-
-#ifdef CDS_CXX11_LAMBDA_SUPPORT
- CPPUNIT_ASSERT( q.push_front( value_type(511), [](value_type& dest, value_type const& i){ dest.nVal = i.nVal * 2; } ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.push_front( 512, [](value_type& dest, int i){ dest.nVal = i; } ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_front( i, []( int& dest, value_type const& v){ dest = v.nVal; } ) );
- CPPUNIT_ASSERT( i == 512 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- v.nVal = i = 0;
- CPPUNIT_ASSERT( q.pop_front( i, [&v]( int& dest, value_type const& val){ dest = -val.nVal; v.nVal = val.nVal; }) );
- CPPUNIT_ASSERT( i == -511 * 2 );
- CPPUNIT_ASSERT( v.nVal == 511 * 2);
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-#endif
-
- // push_left/pop_right
- CPPUNIT_ASSERT( q.push_front( value_type(5) ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.push_front( 10, assign_functor() )) ; // functor
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.push_front( 20, assign_func )) ; // function
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
-
- CPPUNIT_ASSERT( q.pop_back(v) );
- CPPUNIT_ASSERT( v.nVal == 5 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_back(v) );
- CPPUNIT_ASSERT( v.nVal == 10 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.pop_back(v) );
- CPPUNIT_ASSERT( v.nVal == 20 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
-#ifdef CDS_EMPLACE_SUPPORT
- CPPUNIT_ASSERT( q.emplace_front( 157 ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.emplace_front( 158 ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_back(i, pop_func) );
- CPPUNIT_ASSERT( i == 157 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.pop_back(i, pop_functor()) );
- CPPUNIT_ASSERT( i == 158 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-#endif
-
-#ifdef CDS_CXX11_LAMBDA_SUPPORT
- CPPUNIT_ASSERT( q.push_front( value_type(511), [](value_type& dest, value_type const& i){ dest.nVal = i.nVal * 2; } ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- CPPUNIT_ASSERT( q.push_front( 512, [](value_type& dest, int i){ dest.nVal = i * 3; } ));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
-
- CPPUNIT_ASSERT( q.pop_back( i, []( int& dest, value_type const& v){ dest = v.nVal; } ) );
- CPPUNIT_ASSERT( i == 511 * 2 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
-
- v.nVal = i = 0;
- CPPUNIT_ASSERT( q.pop_back( i, [&v]( int& dest, value_type const& val){ dest = -val.nVal; v.nVal = val.nVal; }) );
- CPPUNIT_ASSERT( i == -512 * 3 );
- CPPUNIT_ASSERT( v.nVal == 512 * 3);
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-#endif
-
- // clear test
- for ( int i = 0; i < 1000; i++ ) {
- CPPUNIT_ASSERT( q.push_back( value_type(i) ));
- CPPUNIT_ASSERT( q.push_front( value_type(i * 1024) ));
- }
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2000 ));
- q.clear();
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
- }
-
- void test_MichaelDeque_HP();
- void test_MichaelDeque_HP_ic();
- void test_MichaelDeque_HP_stat();
- void test_MichaelDeque_HP_noalign();
-
- void test_MichaelDeque_PTB();
- void test_MichaelDeque_PTB_ic();
- void test_MichaelDeque_PTB_stat();
- void test_MichaelDeque_PTB_noalign();
-
- CPPUNIT_TEST_SUITE(DequeHeaderTest)
- CPPUNIT_TEST( test_MichaelDeque_HP);
- CPPUNIT_TEST( test_MichaelDeque_HP_ic);
- CPPUNIT_TEST( test_MichaelDeque_HP_stat);
- CPPUNIT_TEST( test_MichaelDeque_HP_noalign);
-
- CPPUNIT_TEST( test_MichaelDeque_PTB);
- CPPUNIT_TEST( test_MichaelDeque_PTB_ic);
- CPPUNIT_TEST( test_MichaelDeque_PTB_stat);
- CPPUNIT_TEST( test_MichaelDeque_PTB_noalign);
-
- CPPUNIT_TEST_SUITE_END()
-
- };
-} // namespace deque
+++ /dev/null
-//$$CDS-header$$
-
-#include "cppunit/cppunit_proxy.h"
-#include "cppunit/test_beans.h"
-
-namespace deque {
- namespace ci = cds::intrusive;
- namespace co = cds::opt;
-
- class IntrusiveDequeHeaderTest: public CppUnitMini::TestCase
- {
- public:
- template <typename NodeType>
- struct base_hook_item: public NodeType
- {
- int nVal;
- int nDisposeCount;
-
- base_hook_item()
- : nDisposeCount(0)
- {}
- };
-
- template <typename NodeType>
- struct member_hook_item
- {
- int nVal;
- int nDisposeCount;
- NodeType hMember;
-
- member_hook_item()
- : nDisposeCount(0)
- {}
- };
-
- struct faked_disposer
- {
- template <typename T>
- void operator ()( T * p )
- {
- ++p->nDisposeCount;
- }
- };
-
- template <class Deque>
- void test()
- {
- test_beans::check_item_counter<typename Deque::item_counter> check_ic;
-
- typedef typename Deque::value_type value_type;
- value_type v1, v2, v3;
-
- Deque q;
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
-
- v1.nVal = 1;
- v2.nVal = 2;
- v3.nVal = 3;
-
- // push_left / pop_right
- CPPUNIT_ASSERT( q.push_front(v1));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
- CPPUNIT_ASSERT( q.push_front(v2));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
- CPPUNIT_ASSERT( q.push_front(v3));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
-
- CPPUNIT_ASSERT( v1.nDisposeCount == 0 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 0 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 0 );
-
- value_type * pv;
- pv = q.pop_back();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 1 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 0 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 0 );
-
- pv = q.pop_back();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 2 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 0 );
-
- pv = q.pop_back();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 3 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
-
- pv = q.pop_back();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv == nullptr );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
-
-
- // push_right / pop_left
- CPPUNIT_ASSERT( q.push_back(v1));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
- CPPUNIT_ASSERT( q.push_back(v2));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
- CPPUNIT_ASSERT( q.push_back(v3));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
-
- CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
-
- pv = q.pop_front();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 1 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
-
- pv = q.pop_front();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 2 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
-
- pv = q.pop_front();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 3 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 2 );
-
- pv = q.pop_front();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv == nullptr );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 2 );
-
-
- // push_right / pop_right
- CPPUNIT_ASSERT( q.push_back(v1));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
- CPPUNIT_ASSERT( q.push_back(v2));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
- CPPUNIT_ASSERT( q.push_back(v3));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
-
- CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 2 );
-
- pv = q.pop_back();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 3 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
-
- pv = q.pop_back();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 2 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
-
- pv = q.pop_back();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 1 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
-
- pv = q.pop_back();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv == nullptr );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
-
-
- // push_left / pop_left
- CPPUNIT_ASSERT( q.push_front(v1));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
- CPPUNIT_ASSERT( q.push_front(v2));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
- CPPUNIT_ASSERT( q.push_front(v3));
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
-
- CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
-
- pv = q.pop_front();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 3 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 4 );
-
- pv = q.pop_front();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 2 );
- CPPUNIT_ASSERT( !q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 4 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 4 );
-
- pv = q.pop_front();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv != nullptr );
- CPPUNIT_ASSERT( pv->nVal == 1 );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 4 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 4 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 4 );
-
- pv = q.pop_front();
- Deque::gc::scan();
- CPPUNIT_ASSERT( pv == nullptr );
- CPPUNIT_ASSERT( q.empty() );
- CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
- CPPUNIT_ASSERT( v1.nDisposeCount == 4 );
- CPPUNIT_ASSERT( v2.nDisposeCount == 4 );
- CPPUNIT_ASSERT( v3.nDisposeCount == 4 );
- }
-
- void test_MichaelDeque_HP_default();
- void test_MichaelDeque_HP_default_ic();
- void test_MichaelDeque_HP_default_stat();
- void test_MichaelDeque_HP_base();
- void test_MichaelDeque_HP_member();
- void test_MichaelDeque_HP_base_ic();
- void test_MichaelDeque_HP_member_ic();
- void test_MichaelDeque_HP_base_stat();
- void test_MichaelDeque_HP_member_stat();
- void test_MichaelDeque_HP_base_align();
- void test_MichaelDeque_HP_member_align();
- void test_MichaelDeque_HP_base_noalign();
- void test_MichaelDeque_HP_member_noalign();
- void test_MichaelDeque_PTB_base();
- void test_MichaelDeque_PTB_member();
- void test_MichaelDeque_PTB_base_ic();
- void test_MichaelDeque_PTB_member_ic();
- void test_MichaelDeque_PTB_base_stat();
- void test_MichaelDeque_PTB_member_stat();
- void test_MichaelDeque_PTB_base_align();
- void test_MichaelDeque_PTB_member_align();
- void test_MichaelDeque_PTB_base_noalign();
- void test_MichaelDeque_PTB_member_noalign();
-
- CPPUNIT_TEST_SUITE(IntrusiveDequeHeaderTest)
- CPPUNIT_TEST( test_MichaelDeque_HP_default);
- CPPUNIT_TEST( test_MichaelDeque_HP_default_ic);
- CPPUNIT_TEST( test_MichaelDeque_HP_default_stat);
- CPPUNIT_TEST( test_MichaelDeque_HP_base);
- CPPUNIT_TEST( test_MichaelDeque_HP_member);
- CPPUNIT_TEST( test_MichaelDeque_HP_base_ic);
- CPPUNIT_TEST( test_MichaelDeque_HP_member_ic);
- CPPUNIT_TEST( test_MichaelDeque_HP_base_stat);
- CPPUNIT_TEST( test_MichaelDeque_HP_member_stat);
- CPPUNIT_TEST( test_MichaelDeque_HP_base_align);
- CPPUNIT_TEST( test_MichaelDeque_HP_member_align);
- CPPUNIT_TEST( test_MichaelDeque_HP_base_noalign);
- CPPUNIT_TEST( test_MichaelDeque_HP_member_noalign);
- CPPUNIT_TEST( test_MichaelDeque_PTB_base);
- CPPUNIT_TEST( test_MichaelDeque_PTB_member);
- CPPUNIT_TEST( test_MichaelDeque_PTB_base_ic);
- CPPUNIT_TEST( test_MichaelDeque_PTB_member_ic);
- CPPUNIT_TEST( test_MichaelDeque_PTB_base_stat);
- CPPUNIT_TEST( test_MichaelDeque_PTB_member_stat);
- CPPUNIT_TEST( test_MichaelDeque_PTB_base_align);
- CPPUNIT_TEST( test_MichaelDeque_PTB_member_align);
- CPPUNIT_TEST( test_MichaelDeque_PTB_base_noalign);
- CPPUNIT_TEST( test_MichaelDeque_PTB_member_noalign);
-
- CPPUNIT_TEST_SUITE_END()
- };
-
-} // namespace deque
+++ /dev/null
-//$$CDS-header$$
-
-#include "hdr_intrusive_deque.h"
-#include <cds/gc/hp.h>
-#include <cds/intrusive/michael_deque.h>
-
-namespace deque {
-#define TEST(X) void IntrusiveDequeHeaderTest::test_##X() { test<X>(); }
-
- namespace {
- typedef cds::gc::HP HP;
- typedef ci::michael_deque::node<HP> node_hp;
-
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::base_hook_item< node_hp >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- > MichaelDeque_HP_default;
-
- /// HP + item counter
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::base_hook_item< node_hp >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::item_counter< cds::atomicity::item_counter >
- ,co::memory_model< co::v::sequential_consistent >
- > MichaelDeque_HP_default_ic;
-
- /// HP + stat
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::base_hook_item< node_hp >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::stat< ci::michael_deque::stat<> >
- > MichaelDeque_HP_default_stat;
-
- // HP base hook
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::base_hook_item< node_hp >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<HP> >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- > MichaelDeque_HP_base;
-
- // HP member hook
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::member_hook_item< node_hp >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_hp >, hMember),
- ci::opt::gc<HP>
- >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- > MichaelDeque_HP_member;
-
- /// HP base hook + item counter
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::base_hook_item< node_hp >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<HP> >
- >
- ,co::item_counter< cds::atomicity::item_counter >
- ,co::memory_model< co::v::relaxed_ordering >
- > MichaelDeque_HP_base_ic;
-
- // HP member hook + item counter
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::member_hook_item< node_hp >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_hp >, hMember),
- ci::opt::gc<HP>
- >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::item_counter< cds::atomicity::item_counter >
- > MichaelDeque_HP_member_ic;
-
- // HP base hook + stat
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::base_hook_item< node_hp >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<HP> >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::stat< ci::michael_deque::stat<> >
- > MichaelDeque_HP_base_stat;
-
- // HP member hook + stat
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::member_hook_item< node_hp >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_hp >, hMember),
- ci::opt::gc<HP>
- >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::stat< ci::michael_deque::stat<> >
- > MichaelDeque_HP_member_stat;
-
- // HP base hook + alignment
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::base_hook_item< node_hp >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<HP> >
- >
- ,co::alignment< 32 >
- > MichaelDeque_HP_base_align;
-
- // HP member hook + alignment
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::member_hook_item< node_hp >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_hp >, hMember),
- ci::opt::gc<HP>
- >
- >
- ,co::alignment< 32 >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- > MichaelDeque_HP_member_align;
-
- // HP base hook + no alignment
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::base_hook_item< node_hp >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<HP> >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::alignment< co::no_special_alignment >
- > MichaelDeque_HP_base_noalign;
-
- // HP member hook + no alignment
- typedef ci::MichaelDeque< HP,
- IntrusiveDequeHeaderTest::member_hook_item< node_hp >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_hp >, hMember),
- ci::opt::gc<HP>
- >
- >
- ,co::alignment< co::no_special_alignment >
- > MichaelDeque_HP_member_noalign;
-
- } // namespace
-
- TEST( MichaelDeque_HP_default)
- TEST( MichaelDeque_HP_default_ic)
- TEST( MichaelDeque_HP_default_stat)
- TEST( MichaelDeque_HP_base)
- TEST( MichaelDeque_HP_member)
- TEST( MichaelDeque_HP_base_ic)
- TEST( MichaelDeque_HP_member_ic)
- TEST( MichaelDeque_HP_base_stat)
- TEST( MichaelDeque_HP_member_stat)
- TEST( MichaelDeque_HP_base_align)
- TEST( MichaelDeque_HP_member_align)
- TEST( MichaelDeque_HP_base_noalign)
- TEST( MichaelDeque_HP_member_noalign)
-
-} // namespace deque
-
-CPPUNIT_TEST_SUITE_REGISTRATION(deque::IntrusiveDequeHeaderTest);
+++ /dev/null
-//$$CDS-header$$
-
-#include "hdr_intrusive_deque.h"
-#include <cds/gc/ptb.h>
-#include <cds/intrusive/michael_deque.h>
-
-namespace deque {
-#define TEST(X) void IntrusiveDequeHeaderTest::test_##X() { test<X>(); }
-
- namespace {
- typedef cds::gc::PTB PTB;
- typedef ci::michael_deque::node<PTB> node_ptb;
-
- // PTB base hook
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::base_hook_item< node_ptb >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<PTB> >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- > MichaelDeque_PTB_base;
-
- // PTB member hook
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::member_hook_item< node_ptb >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_ptb >, hMember),
- ci::opt::gc<PTB>
- >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- > MichaelDeque_PTB_member;
-
- /// PTB base hook + item counter
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::base_hook_item< node_ptb >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<PTB> >
- >
- ,co::item_counter< cds::atomicity::item_counter >
- ,co::memory_model< co::v::relaxed_ordering >
- > MichaelDeque_PTB_base_ic;
-
- // PTB member hook + item counter
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::member_hook_item< node_ptb >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_ptb >, hMember),
- ci::opt::gc<PTB>
- >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::item_counter< cds::atomicity::item_counter >
- > MichaelDeque_PTB_member_ic;
-
- // PTB base hook + stat
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::base_hook_item< node_ptb >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<PTB> >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::stat< ci::michael_deque::stat<> >
- > MichaelDeque_PTB_base_stat;
-
- // PTB member hook + stat
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::member_hook_item< node_ptb >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_ptb >, hMember),
- ci::opt::gc<PTB>
- >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::stat< ci::michael_deque::stat<> >
- > MichaelDeque_PTB_member_stat;
-
- // PTB base hook + alignment
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::base_hook_item< node_ptb >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<PTB> >
- >
- ,co::alignment< 32 >
- > MichaelDeque_PTB_base_align;
-
- // PTB member hook + alignment
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::member_hook_item< node_ptb >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_ptb >, hMember),
- ci::opt::gc<PTB>
- >
- >
- ,co::alignment< 32 >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- > MichaelDeque_PTB_member_align;
-
- // PTB base hook + no alignment
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::base_hook_item< node_ptb >
- ,ci::opt::hook<
- ci::michael_deque::base_hook< ci::opt::gc<PTB> >
- >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,co::alignment< co::no_special_alignment >
- > MichaelDeque_PTB_base_noalign;
-
- // PTB member hook + no alignment
- typedef ci::MichaelDeque< PTB,
- IntrusiveDequeHeaderTest::member_hook_item< node_ptb >
- ,ci::opt::disposer< IntrusiveDequeHeaderTest::faked_disposer >
- ,ci::opt::hook<
- ci::michael_deque::member_hook<
- offsetof(IntrusiveDequeHeaderTest::member_hook_item< node_ptb >, hMember),
- ci::opt::gc<PTB>
- >
- >
- ,co::alignment< co::no_special_alignment >
- > MichaelDeque_PTB_member_noalign;
- } // namespace
-
- TEST( MichaelDeque_PTB_base)
- TEST( MichaelDeque_PTB_member)
- TEST( MichaelDeque_PTB_base_ic)
- TEST( MichaelDeque_PTB_member_ic)
- TEST( MichaelDeque_PTB_base_stat)
- TEST( MichaelDeque_PTB_member_stat)
- TEST( MichaelDeque_PTB_base_align)
- TEST( MichaelDeque_PTB_member_align)
- TEST( MichaelDeque_PTB_base_noalign)
- TEST( MichaelDeque_PTB_member_noalign)
-
-
-} // namespace deque
-
+++ /dev/null
-//$$CDS-header$$
-
-#include "hdr_deque.h"
-#include <cds/gc/hp.h>
-#include <cds/container/michael_deque.h>
-
-namespace deque {
-#define TEST(X) void DequeHeaderTest::test_##X() { test<X>(); }
-
- namespace cc = cds::container;
- namespace co = cds::opt;
-
- namespace {
- typedef cds::gc::HP HP;
- typedef deque::DequeHeaderTest::value_type value_type;
-
- typedef cc::MichaelDeque< HP, value_type > MichaelDeque_HP;
-
- /// HP + item counter
- typedef cc::MichaelDeque< HP, value_type
- ,co::item_counter< cds::atomicity::item_counter >
- ,co::memory_model< co::v::sequential_consistent >
- > MichaelDeque_HP_ic;
-
- /// HP + stat
- typedef cc::MichaelDeque< HP, value_type
- ,co::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDeque_HP_stat;
-
- /// HP + noalign
- typedef cc::MichaelDeque< HP, value_type
- ,co::alignment< co::no_special_alignment >
- ,co::item_counter< cds::atomicity::item_counter >
- > MichaelDeque_HP_noalign;
-
- } // namespace
-
- TEST( MichaelDeque_HP)
- TEST( MichaelDeque_HP_ic)
- TEST( MichaelDeque_HP_stat)
- TEST( MichaelDeque_HP_noalign)
-
-} // namespace deque
-
-CPPUNIT_TEST_SUITE_REGISTRATION(deque::DequeHeaderTest);
+++ /dev/null
-//$$CDS-header$$
-
-#include "hdr_deque.h"
-#include <cds/gc/ptb.h>
-#include <cds/container/michael_deque.h>
-
-namespace deque {
-#define TEST(X) void DequeHeaderTest::test_##X() { test<X>(); }
-
- namespace cc = cds::container;
- namespace co = cds::opt;
-
- namespace {
- typedef cds::gc::PTB PTB;
- typedef deque::DequeHeaderTest::value_type value_type;
-
- typedef cc::MichaelDeque< PTB, value_type > MichaelDeque_PTB;
-
- /// PTB + item counter
- typedef cc::MichaelDeque< PTB, value_type
- ,co::item_counter< cds::atomicity::item_counter >
- ,co::memory_model< co::v::sequential_consistent >
- > MichaelDeque_PTB_ic;
-
- /// PTB + stat
- typedef cc::MichaelDeque< PTB, value_type
- ,co::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDeque_PTB_stat;
-
- /// PTB + noalign
- typedef cc::MichaelDeque< PTB, value_type
- ,co::alignment< co::no_special_alignment >
- ,co::item_counter< cds::atomicity::item_counter >
- > MichaelDeque_PTB_noalign;
-
- } // namespace
-
- TEST( MichaelDeque_PTB)
- TEST( MichaelDeque_PTB_ic)
- TEST( MichaelDeque_PTB_stat)
- TEST( MichaelDeque_PTB_noalign)
-
-} // namespace deque
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef __UNIT_PRINT_DEQUE_STAT_H
-#define __UNIT_PRINT_DEQUE_STAT_H
-
-#include <cds/intrusive/michael_deque.h>
-#include <ostream>
-
-namespace std {
-
- inline ostream& operator <<( ostream& o, cds::intrusive::deque_stat<> const& s )
- {
- return o << "\tStatistics:\n"
- << "\t\t Push front: " << s.m_PushFrontCount.get() << "\n"
- << "\t\t Push back: " << s.m_PushBackCount.get() << "\n"
- << "\t\t Pop front: " << s.m_PopFrontCount.get() << "\n"
- << "\t\t Pop back: " << s.m_PopBackCount.get() << "\n"
- << "\t\tPush front contention: " << s.m_PushFrontContentionCount.get() << "\n"
- << "\t\t Push back contention: " << s.m_PushBackContentionCount.get() << "\n"
- << "\t\t Pop front contention: " << s.m_PopFrontContentionCount.get() << "\n"
- << "\t\t Pop back contention: " << s.m_PopBackContentionCount.get() << "\n"
- << "\t\t Pop empty: " << s.m_PopEmptyCount.get() << "\n"
-;
- }
-
- inline ostream& operator <<( ostream& o, cds::intrusive::michael_deque::stat<> const& s )
- {
- return o << static_cast<cds::intrusive::deque_stat<> const&>( s )
- << "\t\t Stabilize front: " << s.m_StabilizeFrontCount.get() << "\n"
- << "\t\t Stabilize back: " << s.m_StabilizeBackCount.get() << "\n"
-;
- }
-
- inline ostream& operator <<( ostream& o, cds::intrusive::michael_deque::dummy_stat const& )
- {
- return o;
- }
-
-} // namespace std
-
-#endif // #ifndef __UNIT_PRINT_DEQUE_STAT_H
CPPUNIT_TEST(BasketQueue_PTB_stat) \
CPPUNIT_TEST(BasketQueue_PTB_seqcst)
-
-// MichaelDeque
-#define CDSUNIT_DECLARE_MichaelDeque \
- TEST_CASE(MichaelDequeL_HP, cds::intrusive::michael_deque::node< cds::gc::HP > ) \
- TEST_CASE(MichaelDequeL_HP_ic, cds::intrusive::michael_deque::node< cds::gc::HP > ) \
- TEST_CASE(MichaelDequeL_HP_stat, cds::intrusive::michael_deque::node< cds::gc::HP > ) \
- TEST_CASE(MichaelDequeL_PTB, cds::intrusive::michael_deque::node< cds::gc::PTB > ) \
- TEST_CASE(MichaelDequeL_PTB_ic, cds::intrusive::michael_deque::node< cds::gc::PTB > ) \
- TEST_CASE(MichaelDequeL_PTB_stat, cds::intrusive::michael_deque::node< cds::gc::PTB > ) \
- TEST_CASE(MichaelDequeR_HP, cds::intrusive::michael_deque::node< cds::gc::HP > ) \
- TEST_CASE(MichaelDequeR_HP_ic, cds::intrusive::michael_deque::node< cds::gc::HP > ) \
- TEST_CASE(MichaelDequeR_HP_stat, cds::intrusive::michael_deque::node< cds::gc::HP > ) \
- TEST_CASE(MichaelDequeR_PTB, cds::intrusive::michael_deque::node< cds::gc::PTB > ) \
- TEST_CASE(MichaelDequeR_PTB_ic, cds::intrusive::michael_deque::node< cds::gc::PTB > ) \
- TEST_CASE(MichaelDequeR_PTB_stat, cds::intrusive::michael_deque::node< cds::gc::PTB > )
-
-#define CDSUNIT_TEST_MichaelDeque \
- CPPUNIT_TEST(MichaelDequeL_HP) \
- CPPUNIT_TEST(MichaelDequeL_HP_ic) \
- CPPUNIT_TEST(MichaelDequeL_HP_stat) \
- CPPUNIT_TEST(MichaelDequeL_PTB) \
- CPPUNIT_TEST(MichaelDequeL_PTB_ic) \
- CPPUNIT_TEST(MichaelDequeL_PTB_stat) \
- CPPUNIT_TEST(MichaelDequeR_HP) \
- CPPUNIT_TEST(MichaelDequeR_HP_ic) \
- CPPUNIT_TEST(MichaelDequeR_HP_stat) \
- CPPUNIT_TEST(MichaelDequeR_PTB) \
- CPPUNIT_TEST(MichaelDequeR_PTB_ic) \
- CPPUNIT_TEST(MichaelDequeR_PTB_stat)
-
-
// TsigasCycleQueue
#define CDSUNIT_DECLARE_TsigasCycleQueue \
TEST_BOUNDED(TsigasCycleQueue_dyn) \
#include <cds/intrusive/vyukov_mpmc_cycle_queue.h>
#include <cds/intrusive/basket_queue.h>
#include <cds/intrusive/fcqueue.h>
-#include <cds/intrusive/michael_deque.h>
#include <cds/intrusive/segmented_queue.h>
#include <cds/gc/hp.h>
#include <boost/intrusive/slist.hpp>
-#include "print_deque_stat.h"
#include "print_segmentedqueue_stat.h"
namespace queue {
namespace details {
struct empty_stat {};
- // MichaelDeque, push right/pop left
- template <typename GC, typename T, CDS_DECL_OPTIONS10>
- class MichaelDequeR: public cds::intrusive::MichaelDeque< GC, T, CDS_OPTIONS10>
- {
- typedef cds::intrusive::MichaelDeque< GC, T, CDS_OPTIONS10> base_class;
- public:
- MichaelDequeR( size_t nMaxItemCount )
- : base_class( (unsigned int) nMaxItemCount, 4 )
- {}
- MichaelDequeR()
- : base_class( 64 * 1024, 4 )
- {}
-
- bool push( T& v )
- {
- return base_class::push_back( v );
- }
- bool enqueue( T& v )
- {
- return push( v );
- }
-
- T * pop()
- {
- return base_class::pop_front();
- }
- T * deque()
- {
- return pop();
- }
- };
-
- // MichaelDeque, push left/pop right
- template <typename GC, typename T, CDS_DECL_OPTIONS10>
- class MichaelDequeL: public cds::intrusive::MichaelDeque< GC, T, CDS_OPTIONS10>
- {
- typedef cds::intrusive::MichaelDeque< GC, T, CDS_OPTIONS10> base_class;
- public:
- MichaelDequeL( size_t nMaxItemCount )
- : base_class( (unsigned int) nMaxItemCount, 4 )
- {}
- MichaelDequeL()
- : base_class( 64 * 1024, 4 )
- {}
-
- bool push( T& v )
- {
- return base_class::push_front( v );
- }
- bool enqueue( T& v )
- {
- return push( v );
- }
-
- T * pop()
- {
- return base_class::pop_back();
- }
- T * deque()
- {
- return pop();
- }
- };
-
template <typename T, typename Lock=std::mutex>
class BoostSList
{
}
};
-
- // MichaelDeque
- typedef details::MichaelDequeR< cds::gc::HP, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::HP > > >
- > MichaelDequeR_HP;
- typedef details::MichaelDequeR< cds::gc::HP, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::HP > > >
- ,cds::opt::item_counter< cds::atomicity::item_counter >
- > MichaelDequeR_HP_ic;
- typedef details::MichaelDequeR< cds::gc::HP, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::HP > > >
- ,cds::opt::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDequeR_HP_stat;
-
- typedef details::MichaelDequeR< cds::gc::PTB, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::PTB > > >
- > MichaelDequeR_PTB;
- typedef details::MichaelDequeR< cds::gc::PTB, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::PTB > > >
- ,cds::opt::item_counter< cds::atomicity::item_counter >
- > MichaelDequeR_PTB_ic;
- typedef details::MichaelDequeR< cds::gc::PTB, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::PTB > > >
- ,cds::opt::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDequeR_PTB_stat;
-
- typedef details::MichaelDequeL< cds::gc::HP, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::HP > > >
- > MichaelDequeL_HP;
- typedef details::MichaelDequeL< cds::gc::HP, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::HP > > >
- ,cds::opt::item_counter< cds::atomicity::item_counter >
- > MichaelDequeL_HP_ic;
- typedef details::MichaelDequeL< cds::gc::HP, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::HP > > >
- ,cds::opt::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDequeL_HP_stat;
-
-
- typedef details::MichaelDequeL< cds::gc::PTB, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::PTB > > >
- > MichaelDequeL_PTB;
- typedef details::MichaelDequeL< cds::gc::PTB, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::PTB > > >
- ,cds::opt::item_counter< cds::atomicity::item_counter >
- > MichaelDequeL_PTB_ic;
- typedef details::MichaelDequeL< cds::gc::PTB, T
- ,cds::intrusive::opt::hook< cds::intrusive::michael_deque::base_hook< cds::opt::gc< cds::gc::PTB > > >
- ,cds::opt::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDequeL_PTB_stat;
-
// BasketQueue
typedef cds::intrusive::BasketQueue< cds::gc::HP, T
,cds::intrusive::opt::hook< cds::intrusive::basket_queue::base_hook< cds::opt::gc< cds::gc::HP > > >
CPPUNIT_TEST(RWQueue_Spin_ic) \
CPPUNIT_TEST(RWQueue_Spin_stat)
-
-// MichalDeque
-#define CDSUNIT_DECLARE_MichaelDeque( ITEM_TYPE ) \
- TEST_BOUNDED(MichaelDequeL_HP, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeL_HP_ic, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeL_HP_michaelAlloc, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeL_HP_stat, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeL_PTB, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeL_PTB_ic, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeL_PTB_michaelAlloc, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeL_PTB_stat, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeR_HP, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeR_HP_ic, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeR_HP_michaelAlloc, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeR_HP_stat, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeR_PTB, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeR_PTB_ic, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeR_PTB_michaelAlloc, ITEM_TYPE) \
- TEST_BOUNDED(MichaelDequeR_PTB_stat, ITEM_TYPE)
-
-#define CDSUNIT_TEST_MichaelDeque \
- CPPUNIT_TEST(MichaelDequeL_HP ) \
- CPPUNIT_TEST(MichaelDequeL_HP_ic ) \
- CPPUNIT_TEST(MichaelDequeL_HP_michaelAlloc ) \
- CPPUNIT_TEST(MichaelDequeL_HP_stat ) \
- CPPUNIT_TEST(MichaelDequeL_PTB ) \
- CPPUNIT_TEST(MichaelDequeL_PTB_ic ) \
- CPPUNIT_TEST(MichaelDequeL_PTB_michaelAlloc ) \
- CPPUNIT_TEST(MichaelDequeL_PTB_stat ) \
- CPPUNIT_TEST(MichaelDequeR_HP ) \
- CPPUNIT_TEST(MichaelDequeR_HP_ic ) \
- CPPUNIT_TEST(MichaelDequeR_HP_michaelAlloc ) \
- CPPUNIT_TEST(MichaelDequeR_HP_stat ) \
- CPPUNIT_TEST(MichaelDequeR_PTB ) \
- CPPUNIT_TEST(MichaelDequeR_PTB_ic ) \
- CPPUNIT_TEST(MichaelDequeR_PTB_michaelAlloc ) \
- CPPUNIT_TEST(MichaelDequeR_PTB_stat )
-
-
// TsigasCycleQueue
#define CDSUNIT_DECLARE_TsigasCysleQueue( ITEM_TYPE ) \
TEST_BOUNDED(TsigasCycleQueue_dyn, ITEM_TYPE) \
#include <cds/container/basket_queue.h>
#include <cds/container/fcqueue.h>
#include <cds/container/fcdeque.h>
-#include <cds/container/michael_deque.h>
#include <cds/container/segmented_queue.h>
#include <cds/gc/hp.h>
#include "queue/std_queue.h"
#include "lock/win32_lock.h"
#include "michael_alloc.h"
-#include "print_deque_stat.h"
#include "print_segmentedqueue_stat.h"
#include <boost/container/deque.hpp>
namespace queue {
- namespace details {
- // MichaelDeque, push right/pop left
- template <typename GC, typename T, CDS_DECL_OPTIONS7>
- class MichaelDequeR: public cds::container::MichaelDeque< GC, T, CDS_OPTIONS7>
- {
- typedef cds::container::MichaelDeque< GC, T, CDS_OPTIONS7> base_class;
- public:
- MichaelDequeR( size_t nMaxItemCount )
- : base_class( (unsigned int) nMaxItemCount, 4 )
- {}
- MichaelDequeR()
- : base_class( 64 * 1024, 4 )
- {}
-
- bool push( T const& v )
- {
- return base_class::push_back( v );
- }
- bool enqueue( T const& v )
- {
- return push( v );
- }
-
- bool pop( T& v )
- {
- return base_class::pop_front( v );
- }
- bool deque( T& v )
- {
- return pop(v);
- }
- };
-
- // MichaelDeque, push left/pop right
- template <typename GC, typename T, CDS_DECL_OPTIONS7>
- class MichaelDequeL: public cds::container::MichaelDeque< GC, T, CDS_OPTIONS7>
- {
- typedef cds::container::MichaelDeque< GC, T, CDS_OPTIONS7> base_class;
- public:
- MichaelDequeL( size_t nMaxItemCount )
- : base_class( (unsigned int) nMaxItemCount, 4 )
- {}
- MichaelDequeL()
- : base_class( 64 * 1024, 4 )
- {}
-
- bool push( T const& v )
- {
- return base_class::push_front( v );
- }
- bool enqueue( T const& v )
- {
- return push( v );
- }
-
- bool pop( T& v )
- {
- return base_class::pop_back( v );
- }
- bool deque( T& v )
- {
- return pop(v);
- }
- };
-
template <typename T, typename Traits=cds::container::fcdeque::type_traits, class Deque=std::deque<T> >
class FCDequeL: public cds::container::FCDeque<T, Deque, Traits >
{
}
};
-
- // MichaelDeque
- typedef details::MichaelDequeR< cds::gc::HP, Value > MichaelDequeR_HP;
- typedef details::MichaelDequeR< cds::gc::HP, Value
- ,cds::opt::item_counter< cds::atomicity::item_counter >
- > MichaelDequeR_HP_ic;
- typedef details::MichaelDequeR< cds::gc::HP, Value
- ,cds::opt::allocator< memory::MichaelAllocator<int> >
- > MichaelDequeR_HP_michaelAlloc;
- typedef details::MichaelDequeR< cds::gc::HP, Value
- ,cds::opt::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDequeR_HP_stat;
-
- typedef details::MichaelDequeR< cds::gc::PTB, Value > MichaelDequeR_PTB;
- typedef details::MichaelDequeR< cds::gc::PTB, Value
- ,cds::opt::item_counter< cds::atomicity::item_counter >
- > MichaelDequeR_PTB_ic;
- typedef details::MichaelDequeR< cds::gc::PTB, Value
- ,cds::opt::allocator< memory::MichaelAllocator<int> >
- > MichaelDequeR_PTB_michaelAlloc;
- typedef details::MichaelDequeR< cds::gc::PTB, Value
- ,cds::opt::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDequeR_PTB_stat;
-
- typedef details::MichaelDequeL< cds::gc::HP, Value > MichaelDequeL_HP;
- typedef details::MichaelDequeL< cds::gc::HP, Value
- ,cds::opt::item_counter< cds::atomicity::item_counter >
- > MichaelDequeL_HP_ic;
- typedef details::MichaelDequeL< cds::gc::HP, Value
- ,cds::opt::allocator< memory::MichaelAllocator<int> >
- > MichaelDequeL_HP_michaelAlloc;
- typedef details::MichaelDequeL< cds::gc::HP, Value
- ,cds::opt::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDequeL_HP_stat;
-
-
- typedef details::MichaelDequeL< cds::gc::PTB, Value > MichaelDequeL_PTB;
- typedef details::MichaelDequeL< cds::gc::PTB, Value
- ,cds::opt::item_counter< cds::atomicity::item_counter >
- > MichaelDequeL_PTB_ic;
- typedef details::MichaelDequeL< cds::gc::PTB, Value
- ,cds::opt::allocator< memory::MichaelAllocator<int> >
- > MichaelDequeL_PTB_michaelAlloc;
- typedef details::MichaelDequeL< cds::gc::PTB, Value
- ,cds::opt::stat< cds::intrusive::michael_deque::stat<> >
- > MichaelDequeL_PTB_stat;
-
// BasketQueue
typedef cds::container::BasketQueue<
cds::gc::HP , Value
#include "cppunit/thread.h"
#include "stack/intrusive_stack_type.h"
-#include "print_deque_stat.h"
// Multi-threaded stack test for push/pop operation
namespace istack {
#include "cppunit/thread.h"
#include "stack/stack_type.h"
-#include "print_deque_stat.h"
// Multi-threaded stack test for push operation
namespace stack {
#include "cppunit/thread.h"
#include "stack/stack_type.h"
-#include "print_deque_stat.h"
// Multi-threaded stack test for push/pop operation
namespace stack {