# define CDS_TSAN_ANNOTATE_IGNORE_RW_END \\r
CDS_TSAN_ANNOTATE_IGNORE_WRITES_END;\\r
CDS_TSAN_ANNOTATE_IGNORE_READS_END\r
-# define CDS_TSAN_ANNOTATE_NEW_MEMORY( addr, sz ) AnnotateNewMemory( __FILE__, __LINE__, addr, sz )\r
+# define CDS_TSAN_ANNOTATE_NEW_MEMORY( addr, sz ) AnnotateNewMemory( (char *) __FILE__, __LINE__, reinterpret_cast<void *>(addr), sz )\r
\r
// provided by TSan\r
extern "C" {\r
typedef typename node_type::marked_ptr marked_ptr;
typedef typename node_type::atomic_marked_ptr atomic_marked_ptr;
- typedef intrusive::node_to_value<BasketQueue> node_to_value;
typedef typename opt::details::alignment_setter< atomic_marked_ptr, traits::alignment >::type aligned_node_ptr;
typedef typename opt::details::alignment_setter< node_type, traits::alignment >::type dummy_node_type;
//@cond
- template <size_t Count>
- static marked_ptr guard_node( typename gc::template GuardArray<Count>& g, size_t idx, atomic_marked_ptr const& p )
- {
- marked_ptr pg;
- while ( true ) {
- pg = p.load( memory_model::memory_order_relaxed );
- g.assign( idx, node_traits::to_value_ptr( pg.ptr() ) );
- if ( p.load( memory_model::memory_order_acquire) == pg ) {
- return pg;
- }
- }
- }
-
- static marked_ptr guard_node( typename gc::Guard& g, atomic_marked_ptr const& p )
- {
- marked_ptr pg;
- while ( true ) {
- pg = p.load( memory_model::memory_order_relaxed );
- g.assign( node_traits::to_value_ptr( pg.ptr() ) );
- if ( p.load( memory_model::memory_order_acquire) == pg ) {
- return pg;
- }
- }
- }
-
struct dequeue_result {
typename gc::template GuardArray<3> guards;
node_type * pNext;
marked_ptr pNext;
while ( true ) {
- h = guard_node( res.guards, 0, m_pHead );
- t = guard_node( res.guards, 1, m_pTail );
- pNext = guard_node( res.guards, 2, h->m_pNext );
+ h = res.guards.protect( 0, m_pHead, []( marked_ptr p ) -> value_type * { return node_traits::to_value_ptr( p.ptr() );});
+ t = res.guards.protect( 1, m_pTail, []( marked_ptr p ) -> value_type * { return node_traits::to_value_ptr( p.ptr() );});
+ pNext = res.guards.protect( 2, h->m_pNext, []( marked_ptr p ) -> value_type * { return node_traits::to_value_ptr( p.ptr() );});
if ( h == m_pHead.load( memory_model::memory_order_acquire ) ) {
if ( h.ptr() == t.ptr() ) {
{
typename gc::Guard g;
while ( pNext->m_pNext.load(memory_model::memory_order_relaxed).ptr() && m_pTail.load(memory_model::memory_order_relaxed) == t ) {
- pNext = guard_node( g, pNext->m_pNext );
- res.guards.assign( 2, g.template get<value_type>() );
+ pNext = g.protect( pNext->m_pNext, []( marked_ptr p ) -> value_type * { return node_traits::to_value_ptr( p.ptr() );});
+ res.guards.copy( 2, g );
}
}
while ( pNext.ptr() && pNext.bits() && iter.ptr() != t.ptr() && m_pHead.load(memory_model::memory_order_relaxed) == h ) {
iter = pNext;
g.assign( res.guards.template get<value_type>(2) );
- pNext = guard_node( res.guards, 2, pNext->m_pNext );
+ pNext = res.guards.protect( 2, pNext->m_pNext, []( marked_ptr p ) -> value_type * { return node_traits::to_value_ptr( p.ptr() );});
++hops;
}
typename gc::template GuardArray<2> guards;
guards.assign( 0, node_traits::to_value_ptr(head.ptr()) );
while ( head.ptr() != newHead.ptr() ) {
- marked_ptr pNext = guard_node( guards, 1, head->m_pNext );
+ marked_ptr pNext = guards.protect( 1, head->m_pNext, []( marked_ptr p ) -> value_type * { return node_traits::to_value_ptr( p.ptr() );});
assert( pNext.bits() != 0 );
dispose_node( head.ptr() );
- guards.assign( 0, guards.template get<value_type>(1) );
+ guards.copy( 0, 1 );
head = pNext;
}
}
marked_ptr t;
while ( true ) {
- t = guard_node( guard, m_pTail );
+ t = guard.protect( m_pTail, []( marked_ptr p ) -> value_type * { return node_traits::to_value_ptr( p.ptr() );});
marked_ptr pNext = t->m_pNext.load(memory_model::memory_order_acquire );
typename gc::Guard gNext;
try_again:
- pNext = guard_node( gNext, t->m_pNext );
+ pNext = gNext.protect( t->m_pNext, []( marked_ptr p ) -> value_type * { return node_traits::to_value_ptr( p.ptr() );});
// add to the basket
if ( m_pTail.load(memory_model::memory_order_relaxed) == t
protected:
//@cond
typedef typename base_class::dequeue_result dequeue_result;
- typedef typename base_class::node_to_value node_to_value;
bool do_dequeue( dequeue_result& res )
{
node_type * pNext;
node_type * h;
while ( true ) {
- h = res.guards.protect( 0, base_class::m_pHead, node_to_value() );
- pNext = res.guards.protect( 1, h->m_pNext, node_to_value() );
+ h = res.guards.protect( 0, base_class::m_pHead, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );});
+ pNext = res.guards.protect( 1, h->m_pNext, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );});
if ( pNext == nullptr ) {
base_class::m_Stat.onEmptyDequeue();
// 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");
- typedef intrusive::node_to_value<MSQueue> node_to_value;
typedef typename opt::details::alignment_setter< typename node_type::atomic_node_ptr, traits::alignment >::type aligned_node_ptr;
typedef typename opt::details::alignment_setter< node_type, traits::alignment >::type dummy_node_type;
node_type * h;
while ( true ) {
- h = res.guards.protect( 0, m_pHead, node_to_value() );
- pNext = h->m_pNext.load( memory_model::memory_order_acquire );
- res.guards.assign( 1, node_to_value()( pNext ));
+ h = res.guards.protect( 0, m_pHead, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );});
+ pNext = res.guards.protect( 1, h->m_pNext, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );});
if ( m_pHead.load(memory_model::memory_order_acquire) != h )
continue;
node_type * t;
while ( true ) {
- t = guard.protect( m_pTail, node_to_value() );
+ t = guard.protect( m_pTail, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );});
node_type * pNext = t->m_pNext.load(memory_model::memory_order_acquire);
if ( pNext != nullptr ) {
bool empty() const
{
typename gc::Guard guard;
- return guard.protect( m_pHead, node_to_value() )->m_pNext.load( memory_model::memory_order_relaxed ) == nullptr;
+ return guard.protect( m_pHead, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );})
+ ->m_pNext.load( memory_model::memory_order_relaxed ) == nullptr;
}
/// Clear the queue
protected:
//@cond
- typedef intrusive::node_to_value<OptimisticQueue> node_to_value;
typedef typename opt::details::alignment_setter< typename node_type::atomic_node_ptr, traits::alignment >::type aligned_node_ptr;
// GC and node_type::gc must be the same
back_off bkoff;
while ( true ) { // Try till success or empty
- pHead = res.guards.protect( 0, m_pHead, node_to_value() );
- pTail = res.guards.protect( 1, m_pTail, node_to_value() );
+ pHead = res.guards.protect( 0, m_pHead, [](node_type * p) -> value_type * {return node_traits::to_value_ptr(p);});
+ pTail = res.guards.protect( 1, m_pTail, [](node_type * p) -> value_type * {return node_traits::to_value_ptr(p);});
assert( pHead != nullptr );
- pFirstNodePrev = res.guards.protect( 2, pHead->m_pPrev, node_to_value() );
+ pFirstNodePrev = res.guards.protect( 2, pHead->m_pPrev, [](node_type * p) -> value_type * {return node_traits::to_value_ptr(p);});
if ( pHead == m_pHead.load(memory_model::memory_order_relaxed)) {
if ( pTail != pHead ) {
pCurNode = pTail;
while ( pCurNode != pHead ) { // While not at head
- pCurNodeNext = guards.protect(0, pCurNode->m_pNext, node_to_value() );
+ pCurNodeNext = guards.protect(0, pCurNode->m_pNext, [](node_type * p) -> value_type * {return node_traits::to_value_ptr(p);} );
if ( pHead != m_pHead.load(memory_model::memory_order_relaxed) )
break;
pCurNodeNext->m_pPrev.store( pCurNode, memory_model::memory_order_release );
back_off bkoff;
guards.assign( 1, &val );
- node_type * pTail = guards.protect( 0, m_pTail, node_to_value() ) ; // Read the tail
+ node_type * pTail = guards.protect( 0, m_pTail, [](node_type * p) -> value_type * {return node_traits::to_value_ptr(p);} ); // Read the tail
while( true ) {
pNew->m_pNext.store( pTail, memory_model::memory_order_release );
- if ( m_pTail.compare_exchange_strong( pTail, pNew, memory_model::memory_order_release, atomics::memory_order_relaxed ) ) { // Try to CAS the tail
- pTail->m_pPrev.store( pNew, memory_model::memory_order_release ) ; // Success, write prev
+ if ( m_pTail.compare_exchange_strong( pTail, pNew, memory_model::memory_order_release, atomics::memory_order_relaxed )) { // Try to CAS the tail
+ pTail->m_pPrev.store( pNew, memory_model::memory_order_release ); // Success, write prev
++m_ItemCounter;
m_Stat.onEnqueue();
break ; // Enqueue done!
}
- guards.assign( 0, node_traits::to_value_ptr( pTail ) ) ; // pTail has been changed by CAS above
+ guards.assign( 0, node_traits::to_value_ptr( pTail )); // pTail has been changed by CAS above
m_Stat.onEnqueueRace();
bkoff();
}