summaryrefslogtreecommitdiff
path: root/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/lockfree/detail/tagged_ptr_ptrcompression.hpp')
-rw-r--r--boost/lockfree/detail/tagged_ptr_ptrcompression.hpp175
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 */