diff options
Diffstat (limited to 'boost/lockfree/detail/tagged_ptr_ptrcompression.hpp')
-rw-r--r-- | boost/lockfree/detail/tagged_ptr_ptrcompression.hpp | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp b/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp new file mode 100644 index 0000000000..e99e6bff6c --- /dev/null +++ b/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp @@ -0,0 +1,175 @@ +// tagged pointer, for aba prevention +// +// Copyright (C) 2008, 2009 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 <cstddef> /* for std::size_t */ +#include <limits> + +#include <boost/cstdint.hpp> + +#include <boost/lockfree/detail/branch_hints.hpp> + +namespace boost { +namespace lockfree { +namespace detail { + +#if defined (__x86_64__) || defined (_M_X64) + +template <class T> +class tagged_ptr +{ + typedef boost::uint64_t compressed_ptr_t; + +public: + typedef boost::uint16_t tag_t; + +private: + union cast_unit + { + compressed_ptr_t value; + tag_t tag[4]; + }; + + static const int tag_index = 3; + static const 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, int tag) + { + cast_unit ret; + ret.value = compressed_ptr_t(ptr); + ret.tag[tag_index] = tag; + return ret.value; + } + +public: + /** uninitialized constructor */ + tagged_ptr(void) BOOST_NOEXCEPT//: ptr(0), tag(0) + {} + + /** copy constructor */ +#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + tagged_ptr(tagged_ptr const & p): + ptr(p.ptr) + {} +#else + tagged_ptr(tagged_ptr const & p) = default; +#endif + + explicit tagged_ptr(T * p, tag_t t = 0): + ptr(pack_ptr(p, t)) + {} + + /** unsafe set operation */ + /* @{ */ +#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + tagged_ptr & operator= (tagged_ptr const & p) + { + ptr = p.ptr; + return *this; + } +#else + tagged_ptr & operator= (tagged_ptr const & p) = default; +#endif + + void set(T * p, tag_t t) + { + ptr = pack_ptr(p, t); + } + /* @} */ + + /** comparing semantics */ + /* @{ */ + bool operator== (volatile tagged_ptr const & p) const + { + return (ptr == p.ptr); + } + + bool operator!= (volatile tagged_ptr const & p) 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() + 1) & (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 detail */ +} /* namespace lockfree */ +} /* namespace boost */ + +#endif /* BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED */ |