X-Git-Url: http://plrg.eecs.uci.edu/git/?p=libcds.git;a=blobdiff_plain;f=cds%2Fintrusive%2Ffree_list_tagged.h;h=af3e7875261eca99d2a4f0df28f58ec64fa31a98;hp=d1fbbd5dec523bf42f4e56e750ff6697676df9ff;hb=bce7cbd187ae50a4a86d597ac66e825389f67d53;hpb=7448008aa977fe42a83738fbbc63ce11d8ab86f9
diff --git a/cds/intrusive/free_list_tagged.h b/cds/intrusive/free_list_tagged.h
index d1fbbd5d..af3e7875 100644
--- a/cds/intrusive/free_list_tagged.h
+++ b/cds/intrusive/free_list_tagged.h
@@ -5,7 +5,7 @@
Source code repo: http://github.com/khizmax/libcds/
Download: http://sourceforge.net/projects/libcds/files/
-
+
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -25,7 +25,7 @@
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CDSLIB_INTRUSIVE_FREE_LIST_TAGGED_H
@@ -36,7 +36,8 @@
namespace cds { namespace intrusive {
/// Lock-free free list based on tagged pointers (required double-width CAS)
- /** @ingroup cds_intrusive_helper
+ /** @ingroup cds_intrusive_freelist
+
This variant of \p FreeList is intended for processor architectures that support double-width CAS.
It uses tagged pointer technique to solve ABA problem.
@@ -92,9 +93,31 @@ namespace cds { namespace intrusive {
//@endcond
};
+ private:
+ //@cond
+ struct tagged_ptr
+ {
+ node * ptr;
+ uintptr_t tag;
+
+ tagged_ptr()
+ : ptr( nullptr )
+ , tag( 0 )
+ {}
+
+ tagged_ptr( node* p )
+ : ptr( p )
+ , tag( 0 )
+ {}
+ };
+
+ static_assert(sizeof( tagged_ptr ) == sizeof( void * ) * 2, "sizeof( tagged_ptr ) violation");
+ //@endcond
+
public:
/// Creates empty free-list
TaggedFreeList()
+ : m_Head( tagged_ptr())
{
// Your platform must support double-width CAS
assert( m_Head.is_lock_free());
@@ -110,16 +133,17 @@ namespace cds { namespace intrusive {
assert( empty() );
}
-
/// Puts \p pNode to the free list
void put( node * pNode )
{
+ assert( m_Head.is_lock_free());
+
tagged_ptr currentHead = m_Head.load( atomics::memory_order_relaxed );
tagged_ptr newHead = { pNode };
do {
newHead.tag = currentHead.tag + 1;
pNode->m_freeListNext.store( currentHead.ptr, atomics::memory_order_relaxed );
- } while ( !m_Head.compare_exchange_weak( currentHead, newHead, atomics::memory_order_release, atomics::memory_order_relaxed ));
+ } while ( cds_unlikely( !m_Head.compare_exchange_weak( currentHead, newHead, atomics::memory_order_release, atomics::memory_order_relaxed )));
}
/// Gets a node from the free list. If the list is empty, returns \p nullptr
@@ -130,7 +154,7 @@ namespace cds { namespace intrusive {
while ( currentHead.ptr != nullptr ) {
newHead.ptr = currentHead.ptr->m_freeListNext.load( atomics::memory_order_relaxed );
newHead.tag = currentHead.tag + 1;
- if ( m_Head.compare_exchange_weak( currentHead, newHead, atomics::memory_order_release, atomics::memory_order_acquire ) )
+ if ( cds_likely( m_Head.compare_exchange_weak( currentHead, newHead, atomics::memory_order_release, atomics::memory_order_acquire )))
break;
}
return currentHead.ptr;
@@ -169,23 +193,10 @@ namespace cds { namespace intrusive {
private:
//@cond
- struct tagged_ptr
- {
- node * ptr;
- uintptr_t tag;
-
- tagged_ptr()
- : ptr( nullptr )
- , tag( 0 )
- {}
- };
-
- static_assert(sizeof( tagged_ptr ) == sizeof(void *) * 2, "sizeof( tagged_ptr ) violation" );
-
atomics::atomic m_Head;
//@endcond
};
}} // namespace cds::intrusive
-#endif // CDSLIB_INTRUSIVE_FREE_LIST_TAGGED_H
\ No newline at end of file
+#endif // CDSLIB_INTRUSIVE_FREE_LIST_TAGGED_H