boost/lockfree/detail/tagged_ptr_ptrcompression.hpp
// tagged pointer, for aba prevention
//
// Copyright (C) 2008, 2009, 2016 Tim Blechmann, based on code by Cory Nelson
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED
#define BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED
#include <cstdint>
#include <limits>
#include <boost/lockfree/detail/prefix.hpp>
namespace boost { namespace lockfree { namespace detail {
#ifdef BOOST_LOCKFREE_PTR_COMPRESSION
template < class T >
class tagged_ptr
{
typedef std::uint64_t compressed_ptr_t;
public:
typedef std::uint16_t tag_t;
private:
union cast_unit
{
compressed_ptr_t value;
tag_t tag[ 4 ];
};
static constexpr int tag_index = 3;
static constexpr compressed_ptr_t ptr_mask = 0xffffffffffffUL; //(1L<<48L)-1;
static T* extract_ptr( volatile compressed_ptr_t const& i )
{
return (T*)( i & ptr_mask );
}
static tag_t extract_tag( volatile compressed_ptr_t const& i )
{
cast_unit cu;
cu.value = i;
return cu.tag[ tag_index ];
}
static compressed_ptr_t pack_ptr( T* ptr, tag_t tag )
{
cast_unit ret;
ret.value = compressed_ptr_t( ptr );
ret.tag[ tag_index ] = tag;
return ret.value;
}
public:
/** uninitialized constructor */
tagged_ptr( void ) noexcept //: ptr(0), tag(0)
{}
/** copy constructor */
tagged_ptr( tagged_ptr const& p ) = default;
explicit tagged_ptr( T* p, tag_t t = 0 ) :
ptr( pack_ptr( p, t ) )
{}
/** unsafe set operation */
/* @{ */
tagged_ptr& operator=( tagged_ptr const& p ) = default;
void set( T* p, tag_t t )
{
ptr = pack_ptr( p, t );
}
/* @} */
/** comparing semantics */
/* @{ */
bool operator==( volatile tagged_ptr const& p ) volatile const
{
return ( ptr == p.ptr );
}
bool operator!=( volatile tagged_ptr const& p ) volatile const
{
return !operator==( p );
}
/* @} */
/** pointer access */
/* @{ */
T* get_ptr() const
{
return extract_ptr( ptr );
}
void set_ptr( T* p )
{
tag_t tag = get_tag();
ptr = pack_ptr( p, tag );
}
/* @} */
/** tag access */
/* @{ */
tag_t get_tag() const
{
return extract_tag( ptr );
}
tag_t get_next_tag() const
{
tag_t next = ( get_tag() + 1u ) & ( std::numeric_limits< tag_t >::max )();
return next;
}
void set_tag( tag_t t )
{
T* p = get_ptr();
ptr = pack_ptr( p, t );
}
/* @} */
/** smart pointer support */
/* @{ */
T& operator*() const
{
return *get_ptr();
}
T* operator->() const
{
return get_ptr();
}
operator bool( void ) const
{
return get_ptr() != 0;
}
/* @} */
protected:
compressed_ptr_t ptr;
};
#else
# error unsupported platform
#endif
}}} // namespace boost::lockfree::detail
#endif /* BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED */