HP refactoring:
[libcds.git] / cds / gc / impl / hp_decl.h
index 1fd30d3987ed765ba1d84a4c95b7186bd531d06d..354ac6a80d7dfbb9bfdaa1340331dfd54bcf67f4 100644 (file)
@@ -1,7 +1,35 @@
-//$$CDS-header$$
-
-#ifndef __CDS_GC_IMPL_HP_DECL_H
-#define __CDS_GC_IMPL_HP_DECL_H
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    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.
+*/
+
+#ifndef CDSLIB_GC_IMPL_HP_DECL_H
+#define CDSLIB_GC_IMPL_HP_DECL_H
 
 #include <stdexcept>    // overflow_error
 #include <cds/gc/details/hp.h>
 
 #include <stdexcept>    // overflow_error
 #include <cds/gc/details/hp.h>
@@ -21,6 +49,9 @@ namespace cds { namespace gc {
             - [2003] Maged M.Michael "Hazard Pointers: Safe memory reclamation for lock-free objects"
             - [2004] Andrei Alexandrescy, Maged Michael "Lock-free Data Structures with Hazard Pointers"
 
             - [2003] Maged M.Michael "Hazard Pointers: Safe memory reclamation for lock-free objects"
             - [2004] Andrei Alexandrescy, Maged Michael "Lock-free Data Structures with Hazard Pointers"
 
+        Hazard Pointer garbage collector is a singleton. The main user-level part of Hazard Pointer schema is
+        GC class \p %cds::gc::HP and its nested classes. Before use any HP-related class you must initialize HP garbage collector
+        by contructing \p %cds::gc::HP object in beginning of your \p main().
         See \ref cds_how_to_use "How to use" section for details how to apply garbage collector.
     */
     class HP
         See \ref cds_how_to_use "How to use" section for details how to apply garbage collector.
     */
     class HP
@@ -56,6 +87,9 @@ namespace cds { namespace gc {
         */
         typedef hp::ThreadGC   thread_gc_impl;
 
         */
         typedef hp::ThreadGC   thread_gc_impl;
 
+        /// Exception "Too many Hazard Pointer"
+        typedef hp::GarbageCollector::too_many_hazard_ptr too_many_hazard_ptr_exception;
+
         /// Wrapper for hp::ThreadGC class
         /**
             @headerfile cds/gc/hp.h
         /// Wrapper for hp::ThreadGC class
         /**
             @headerfile cds/gc/hp.h
@@ -87,34 +121,89 @@ namespace cds { namespace gc {
                 Otherwise it detaches the current thread from Hazard Pointer GC.
             */
             ~thread_gc() ;  // inline in hp_impl.h
                 Otherwise it detaches the current thread from Hazard Pointer GC.
             */
             ~thread_gc() ;  // inline in hp_impl.h
+
+        public: // for internal use only!!!
+            //@cond
+            static cds::gc::hp::details::hp_guard* alloc_guard(); // inline in hp_impl.h
+            static void free_guard( cds::gc::hp::details::hp_guard* g ); // inline in hp_impl.h
+            //@endcond
         };
 
         /// Hazard Pointer guard
         /**
             @headerfile cds/gc/hp.h
 
         };
 
         /// Hazard Pointer guard
         /**
             @headerfile cds/gc/hp.h
 
-            A guard is the hazard pointer.
-            Additionally, the \p %Guard class manages allocation and deallocation of the hazard pointer
+            A guard is a hazard pointer.
+            Additionally, the \p %Guard class manages allocation and deallocation of the hazard pointer.
 
 
-            A \p %Guard object is not copy- and move-constructible 
-            and not copy- and move-assignable.
+            \p %Guard object is movable but not copyable.
+
+            The guard object can be in two states:
+            - unlinked - the guard is not linked with any internal hazard pointer.
+              In this state no operation except \p link() and move assignment is supported.
+            - linked (default) - the guard allocates an internal hazard pointer and fully operable.
+
+            Due to performance reason the implementation does not check state of the guard in runtime.
+
+            @warning Move assignment can transfer the guard in unlinked state, use with care.
         */
         */
-        class Guard : public hp::guard
+        class Guard
         {
         {
-            //@cond
-            typedef hp::guard base_class;
-            //@endcond
-
         public:
         public:
-            /// Default ctor
-            Guard() CDS_NOEXCEPT;   // inline in hp_impl.h
+            /// Default ctor allocates a guard (hazard pointer) from thread-private storage
+            /**
+                @warning Can throw \p too_many_hazard_ptr_exception if internal hazard pointer objects are exhausted.
+            */
+            Guard();  // inline in hp_impl.h
 
 
-            //@cond
+            /// Initilalizes an unlinked guard i.e. the guard contains no hazard pointer. Used for move semantics support
+            explicit Guard( std::nullptr_t ) CDS_NOEXCEPT
+                : m_guard( nullptr )
+            {}
+
+            /// Move ctor - \p src guard becomes unlinked (transfer internal guard ownership)
+            Guard( Guard&& src ) CDS_NOEXCEPT
+                : m_guard( src.m_guard )
+            {
+                src.m_guard = nullptr;
+            }
+
+            /// Move assignment: the internal guards are swapped between \p src and \p this
+            /**
+                @warning \p src will become in unlinked state if \p this was unlinked on entry.
+            */
+            Guard& operator=( Guard&& src ) CDS_NOEXCEPT
+            {
+                std::swap( m_guard, src.m_guard );
+                return *this;
+            }
+
+            /// Copy ctor is prohibited - the guard is not copyable
             Guard( Guard const& ) = delete;
             Guard( Guard const& ) = delete;
-            Guard( Guard&& s ) = delete;
-            Guard& operator=(Guard const&) = delete;
-            Guard& operator=(Guard&&) = delete;
-            //@endcond
+
+            /// Copy assignment is prohibited
+            Guard& operator=( Guard const& ) = delete;
+
+            /// Frees the internal hazard pointer if the guard is in linked state
+            ~Guard()
+            {
+                unlink();
+            }
+
+            /// Checks if the guard object linked with any internal hazard pointer
+            bool is_linked() const
+            {
+                return m_guard != nullptr;
+            }
+
+            /// Links the guard with internal hazard pointer if the guard is in unlinked state
+            /**
+                @warning Can throw \p too_many_hazard_ptr_exception if internal hazard pointer objects are exhausted.
+            */
+            void link(); // inline in hp_impl.h
+
+            /// Unlinks the guard from internal hazard pointer; the guard becomes in unlinked state
+            void unlink(); // inline in hp_impl.h
 
             /// Protects a pointer of type \p atomic<T*>
             /**
 
             /// Protects a pointer of type \p atomic<T*>
             /**
@@ -122,11 +211,15 @@ namespace cds { namespace gc {
 
                 The function tries to load \p toGuard and to store it
                 to the HP slot repeatedly until the guard's value equals \p toGuard
 
                 The function tries to load \p toGuard and to store it
                 to the HP slot repeatedly until the guard's value equals \p toGuard
+
+                @warning The guad object should be in linked state, otherwise the result is undefined
             */
             template <typename T>
             */
             template <typename T>
-            T protect( atomics::atomic<T> const& toGuard ) CDS_NOEXCEPT
+            T protect( atomics::atomic<T> const& toGuard )
             {
             {
-                T pCur = toGuard.load(atomics::memory_order_relaxed);
+                assert( m_guard != nullptr );
+
+                T pCur = toGuard.load(atomics::memory_order_acquire);
                 T pRet;
                 do {
                     pRet = assign( pCur );
                 T pRet;
                 do {
                     pRet = assign( pCur );
@@ -143,19 +236,23 @@ namespace cds { namespace gc {
                 to the HP slot repeatedly until the guard's value equals \p toGuard.
 
                 The function is useful for intrusive containers when \p toGuard is a node pointer
                 to the HP slot repeatedly until the guard's value equals \p toGuard.
 
                 The function is useful for intrusive containers when \p toGuard is a node pointer
-                that should be converted to a pointer to the value type before protecting.
+                that should be converted to a pointer to the value before protecting.
                 The parameter \p f of type Func is a functor that makes this conversion:
                 \code
                     struct functor {
                         value_type * operator()( T * p );
                     };
                 \endcode
                 The parameter \p f of type Func is a functor that makes this conversion:
                 \code
                     struct functor {
                         value_type * operator()( T * p );
                     };
                 \endcode
-                Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
+                Actually, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
+
+                @warning The guad object should be in linked state, otherwise the result is undefined
             */
             template <typename T, class Func>
             T protect( atomics::atomic<T> const& toGuard, Func f )
             {
             */
             template <typename T, class Func>
             T protect( atomics::atomic<T> const& toGuard, Func f )
             {
-                T pCur = toGuard.load(atomics::memory_order_relaxed);
+                assert( m_guard != nullptr );
+
+                T pCur = toGuard.load(atomics::memory_order_acquire);
                 T pRet;
                 do {
                     pRet = pCur;
                 T pRet;
                 do {
                     pRet = pCur;
@@ -169,22 +266,22 @@ namespace cds { namespace gc {
             /**
                 The function equals to a simple assignment the value \p p to guard, no loop is performed.
                 Can be used for a pointer that cannot be changed concurrently
             /**
                 The function equals to a simple assignment the value \p p to guard, no loop is performed.
                 Can be used for a pointer that cannot be changed concurrently
+
+                @warning The guad object should be in linked state, otherwise the result is undefined
             */
             template <typename T>
             */
             template <typename T>
-            T * assign( T * p ) CDS_NOEXCEPT
-            {
-                return base_class::operator =(p);
-            }
+            T * assign( T* p );    // inline in hp_impl.h
 
             //@cond
 
             //@cond
-            std::nullptr_t assign( std::nullptr_t ) CDS_NOEXCEPT
+            std::nullptr_t assign( std::nullptr_t )
             {
             {
-                return base_class::operator =(nullptr);
+                assert(m_guard != nullptr );
+                return *m_guard = nullptr;
             }
             //@endcond
 
             }
             //@endcond
 
-            /// Copy from \p src guard to \p this guard
-            void copy( Guard const& src ) CDS_NOEXCEPT
+            /// Copy a value guarded from \p src guard to \p this guard (valid only in linked state)
+            void copy( Guard const& src )
             {
                 assign( src.get_native() );
             }
             {
                 assign( src.get_native() );
             }
@@ -193,31 +290,48 @@ namespace cds { namespace gc {
             /**
                 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
                 Can be used for a marked pointer that cannot be changed concurrently.
             /**
                 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
                 Can be used for a marked pointer that cannot be changed concurrently.
+
+                @warning The guad object should be in linked state, otherwise the result is undefined
             */
             template <typename T, int BITMASK>
             */
             template <typename T, int BITMASK>
-            T * assign( cds::details::marked_ptr<T, BITMASK> p ) CDS_NOEXCEPT
+            T * assign( cds::details::marked_ptr<T, BITMASK> p )
             {
             {
-                return base_class::operator =( p.ptr() );
+                return assign( p.ptr());
             }
 
             }
 
-            /// Clear value of the guard
-            void clear() CDS_NOEXCEPT
+            /// Clear value of the guard (valid only in linked state)
+            void clear()
             {
                 assign( nullptr );
             }
 
             {
                 assign( nullptr );
             }
 
-            /// Get the value currently protected
+            /// Get the value currently protected (valid only in linked state)
             template <typename T>
             template <typename T>
-            T * get() const CDS_NOEXCEPT
+            T * get() const
             {
                 return reinterpret_cast<T *>( get_native() );
             }
 
             {
                 return reinterpret_cast<T *>( get_native() );
             }
 
-            /// Get native hazard pointer stored
-            guarded_pointer get_native() const CDS_NOEXCEPT
+            /// Get native hazard pointer stored (valid only in linked state)
+            guarded_pointer get_native() const
             {
             {
-                return base_class::get();
+                assert( m_guard != nullptr );
+                return m_guard->get();
             }
             }
+
+            //@cond
+            hp::details::hp_guard* release()
+            {
+                hp::details::hp_guard* g = m_guard;
+                m_guard = nullptr;
+                return g;
+            }
+            //@endcond
+
+        private:
+            //@cond
+            hp::details::hp_guard* m_guard;
+            //@endcond
         };
 
         /// Array of Hazard Pointer guards
         };
 
         /// Array of Hazard Pointer guards
@@ -226,32 +340,38 @@ namespace cds { namespace gc {
             The class is intended for allocating an array of hazard pointer guards.
             Template parameter \p Count defines the size of the array.
 
             The class is intended for allocating an array of hazard pointer guards.
             Template parameter \p Count defines the size of the array.
 
-            A \p %GuardArray object is not copy- and move-constructible
-            and not copy- and move-assignable.
         */
         template <size_t Count>
         */
         template <size_t Count>
-        class GuardArray : public hp::array<Count>
+        class GuardArray
         {
         {
-            //@cond
-            typedef hp::array<Count> base_class;
-            //@endcond
         public:
             /// Rebind array for other size \p Count2
             template <size_t Count2>
             struct rebind {
         public:
             /// Rebind array for other size \p Count2
             template <size_t Count2>
             struct rebind {
-                typedef GuardArray<Count2>  other   ;   ///< rebinding result
+                typedef GuardArray<Count2>  other;   ///< rebinding result
             };
 
             };
 
+            /// Array capacity
+            static CDS_CONSTEXPR const size_t c_nCapacity = Count;
+
         public:
         public:
-            /// Default ctor
-            GuardArray() CDS_NOEXCEPT;  // inline in hp_impl.h
+            /// Default ctor allocates \p Count hazard pointers
+            GuardArray(); // inline in hp_impl.h
 
 
-            //@cond
-            GuardArray( GuardArray const& ) = delete;
+            /// Move ctor is prohibited
             GuardArray( GuardArray&& ) = delete;
             GuardArray( GuardArray&& ) = delete;
-            GuardArray& operator=(GuardArray const&) = delete;
-            GuardArray& operator-(GuardArray&&) = delete;
-            //@endcond
+
+            /// Move assignment is prohibited
+            GuardArray& operator=( GuardArray&& ) = delete;
+
+            /// Copy ctor is prohibited
+            GuardArray( GuardArray const& ) = delete;
+
+            /// Copy assignment is prohibited
+            GuardArray& operator=( GuardArray const& ) = delete;
+
+            /// Frees allocated hazard pointers
+            ~GuardArray(); // inline in hp_impl.h
 
             /// Protects a pointer of type \p atomic<T*>
             /**
 
             /// Protects a pointer of type \p atomic<T*>
             /**
@@ -261,12 +381,14 @@ namespace cds { namespace gc {
                 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
             */
             template <typename T>
                 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
             */
             template <typename T>
-            T protect( size_t nIndex, atomics::atomic<T> const& toGuard ) CDS_NOEXCEPT
+            T protect( size_t nIndex, atomics::atomic<T> const& toGuard )
             {
             {
+                assert( nIndex < capacity());
+
                 T pRet;
                 do {
                     pRet = assign( nIndex, toGuard.load(atomics::memory_order_acquire) );
                 T pRet;
                 do {
                     pRet = assign( nIndex, toGuard.load(atomics::memory_order_acquire) );
-                } while ( pRet != toGuard.load(atomics::memory_order_relaxed));
+                } while ( pRet != toGuard.load(atomics::memory_order_acquire));
 
                 return pRet;
             }
 
                 return pRet;
             }
@@ -291,10 +413,12 @@ namespace cds { namespace gc {
             template <typename T, class Func>
             T protect( size_t nIndex, atomics::atomic<T> const& toGuard, Func f )
             {
             template <typename T, class Func>
             T protect( size_t nIndex, atomics::atomic<T> const& toGuard, Func f )
             {
+                assert( nIndex < capacity() );
+
                 T pRet;
                 do {
                     assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_acquire) ));
                 T pRet;
                 do {
                     assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_acquire) ));
-                } while ( pRet != toGuard.load(atomics::memory_order_relaxed));
+                } while ( pRet != toGuard.load(atomics::memory_order_acquire));
 
                 return pRet;
             }
 
                 return pRet;
             }
@@ -304,11 +428,7 @@ namespace cds { namespace gc {
                 The function equals to a simple assignment, no loop is performed.
             */
             template <typename T>
                 The function equals to a simple assignment, no loop is performed.
             */
             template <typename T>
-            T * assign( size_t nIndex, T * p ) CDS_NOEXCEPT
-            {
-                base_class::set(nIndex, p);
-                return p;
-            }
+            T * assign( size_t nIndex, T * p ); // inline in hp_impl.h
 
             /// Store marked pointer \p p to the guard
             /**
 
             /// Store marked pointer \p p to the guard
             /**
@@ -316,47 +436,268 @@ namespace cds { namespace gc {
                 Can be used for a marked pointer that cannot be changed concurrently.
             */
             template <typename T, int BITMASK>
                 Can be used for a marked pointer that cannot be changed concurrently.
             */
             template <typename T, int BITMASK>
-            T * assign( size_t nIndex, cds::details::marked_ptr<T, BITMASK> p ) CDS_NOEXCEPT
+            T * assign( size_t nIndex, cds::details::marked_ptr<T, BITMASK> p )
             {
                 return assign( nIndex, p.ptr() );
             }
 
             /// Copy guarded value from \p src guard to slot at index \p nIndex
             {
                 return assign( nIndex, p.ptr() );
             }
 
             /// Copy guarded value from \p src guard to slot at index \p nIndex
-            void copy( size_t nIndex, Guard const& src ) CDS_NOEXCEPT
+            void copy( size_t nIndex, Guard const& src )
             {
                 assign( nIndex, src.get_native() );
             }
 
             /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
             {
                 assign( nIndex, src.get_native() );
             }
 
             /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
-            void copy( size_t nDestIndex, size_t nSrcIndex ) CDS_NOEXCEPT
+            void copy( size_t nDestIndex, size_t nSrcIndex )
             {
                 assign( nDestIndex, get_native( nSrcIndex ));
             }
 
             /// Clear value of the slot \p nIndex
             {
                 assign( nDestIndex, get_native( nSrcIndex ));
             }
 
             /// Clear value of the slot \p nIndex
-            void clear( size_t nIndex ) CDS_NOEXCEPT
+            void clear( size_t nIndex )
             {
             {
-                base_class::clear( nIndex );
+                m_arr.clear( nIndex );
             }
 
             /// Get current value of slot \p nIndex
             template <typename T>
             }
 
             /// Get current value of slot \p nIndex
             template <typename T>
-            T * get( size_t nIndex ) const CDS_NOEXCEPT
+            T * get( size_t nIndex ) const
             {
                 return reinterpret_cast<T *>( get_native( nIndex ) );
             }
 
             /// Get native hazard pointer stored
             {
                 return reinterpret_cast<T *>( get_native( nIndex ) );
             }
 
             /// Get native hazard pointer stored
-            guarded_pointer get_native( size_t nIndex ) const CDS_NOEXCEPT
+            guarded_pointer get_native( size_t nIndex ) const
+            {
+                assert( nIndex < capacity() );
+                return m_arr[nIndex]->get();
+            }
+
+            //@cond
+            hp::details::hp_guard* release( size_t nIndex ) CDS_NOEXCEPT
             {
             {
-                return base_class::operator[](nIndex).get();
+                return m_arr.release( nIndex );
             }
             }
+            //@endcond
 
             /// Capacity of the guard array
 
             /// Capacity of the guard array
-            static CDS_CONSTEXPR size_t capacity() CDS_NOEXCEPT
+            static CDS_CONSTEXPR size_t capacity()
+            {
+                return c_nCapacity;
+            }
+
+        private:
+            //@cond
+            hp::details::hp_array<Count> m_arr;
+            //@endcond
+        };
+
+        /// Guarded pointer
+        /**
+            A guarded pointer is a pair of a pointer and GC's guard.
+            Usually, it is used for returning a pointer to the item from an lock-free container.
+            The guard prevents the pointer to be early disposed (freed) by GC.
+            After destructing \p %guarded_ptr object the pointer can be disposed (freed) automatically at any time.
+
+            Template arguments:
+            - \p GuardedType - a type which the guard stores
+            - \p ValueType - a value type
+            - \p Cast - a functor for converting <tt>GuardedType*</tt> to <tt>ValueType*</tt>. Default is \p void (no casting).
+
+            For intrusive containers, \p GuardedType is the same as \p ValueType and no casting is needed.
+            In such case the \p %guarded_ptr is:
+            @code
+            typedef cds::gc::HP::guarded_ptr< foo > intrusive_guarded_ptr;
+            @endcode
+
+            For standard (non-intrusive) containers \p GuardedType is not the same as \p ValueType and casting is needed.
+            For example:
+            @code
+            struct foo {
+                int const   key;
+                std::string value;
+            };
+
+            struct value_accessor {
+                std::string* operator()( foo* pFoo ) const
+                {
+                    return &(pFoo->value);
+                }
+            };
+
+            // Guarded ptr
+            typedef cds::gc::HP::guarded_ptr< Foo, std::string, value_accessor > nonintrusive_guarded_ptr;
+            @endcode
+
+            You don't need use this class directly.
+            All set/map container classes from \p libcds declare the typedef for \p %guarded_ptr with appropriate casting functor.
+        */
+        template <typename GuardedType, typename ValueType=GuardedType, typename Cast=void >
+        class guarded_ptr
+        {
+            //@cond
+            struct trivial_cast {
+                ValueType * operator()( GuardedType * p ) const
+                {
+                    return p;
+                }
+            };
+
+            template <typename GT, typename VT, typename C> friend class guarded_ptr;
+            //@endcond
+
+        public:
+            typedef GuardedType guarded_type; ///< Guarded type
+            typedef ValueType   value_type;   ///< Value type
+
+            /// Functor for casting \p guarded_type to \p value_type
+            typedef typename std::conditional< std::is_same<Cast, void>::value, trivial_cast, Cast >::type value_cast;
+
+        public:
+            /// Creates empty guarded pointer
+            guarded_ptr() CDS_NOEXCEPT
+                : m_pGuard(nullptr)
+            {}
+
+            //@cond
+            explicit guarded_ptr( hp::details::hp_guard* g ) CDS_NOEXCEPT
+                : m_pGuard( g )
+            {}
+
+            /// Initializes guarded pointer with \p p
+            explicit guarded_ptr( guarded_type* p ) CDS_NOEXCEPT
+                : m_pGuard( nullptr )
+            {
+                reset(p);
+            }
+            explicit guarded_ptr( std::nullptr_t ) CDS_NOEXCEPT
+                : m_pGuard( nullptr )
+            {}
+            //@endcond
+
+            /// Move ctor
+            guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
+                : m_pGuard( gp.m_pGuard )
+            {
+                gp.m_pGuard = nullptr;
+            }
+
+            /// Move ctor
+            template <typename GT, typename VT, typename C>
+            guarded_ptr( guarded_ptr<GT, VT, C>&& gp ) CDS_NOEXCEPT
+                : m_pGuard( gp.m_pGuard )
+            {
+                gp.m_pGuard = nullptr;
+            }
+
+            /// Ctor from \p Guard
+            explicit guarded_ptr( Guard&& g ) CDS_NOEXCEPT
+                : m_pGuard( g.release() )
+            {}
+
+            /// The guarded pointer is not copy-constructible
+            guarded_ptr( guarded_ptr const& gp ) = delete;
+
+            /// Clears the guarded pointer
+            /**
+                \ref release() is called if guarded pointer is not \ref empty()
+            */
+            ~guarded_ptr() CDS_NOEXCEPT
+            {
+                release();
+            }
+
+            /// Move-assignment operator
+            guarded_ptr& operator=( guarded_ptr&& gp ) CDS_NOEXCEPT
+            {
+                std::swap( m_pGuard, gp.m_pGuard );
+                return *this;
+            }
+
+            /// Move-assignment from \p Guard
+            guarded_ptr& operator=( Guard&& g ) CDS_NOEXCEPT
+            {
+                std::swap( m_pGuard, g.m_guard );
+                return *this;
+            }
+
+            /// The guarded pointer is not copy-assignable
+            guarded_ptr& operator=(guarded_ptr const& gp) = delete;
+
+            /// Returns a pointer to guarded value
+            value_type * operator ->() const CDS_NOEXCEPT
+            {
+                assert( !empty() );
+                return value_cast()( reinterpret_cast<guarded_type *>(m_pGuard->get()));
+            }
+
+            /// Returns a reference to guarded value
+            value_type& operator *() CDS_NOEXCEPT
+            {
+                assert( !empty());
+                return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
+            }
+
+            /// Returns const reference to guarded value
+            value_type const& operator *() const CDS_NOEXCEPT
+            {
+                assert( !empty() );
+                return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
+            }
+
+            /// Checks if the guarded pointer is \p nullptr
+            bool empty() const CDS_NOEXCEPT
+            {
+                return !m_pGuard || m_pGuard->get( atomics::memory_order_relaxed ) == nullptr;
+            }
+
+            /// \p bool operator returns <tt>!empty()</tt>
+            explicit operator bool() const CDS_NOEXCEPT
+            {
+                return !empty();
+            }
+
+            /// Clears guarded pointer
+            /**
+                If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
+                Dereferncing the guarded pointer after \p release() is dangerous.
+            */
+            void release() CDS_NOEXCEPT
+            {
+                free_guard();
+            }
+
+            //@cond
+            // For internal use only!!!
+            void reset(guarded_type * p) CDS_NOEXCEPT
+            {
+                alloc_guard();
+                assert( m_pGuard );
+                m_pGuard->set(p);
+            }
+            //@endcond
+
+        private:
+            //@cond
+            void alloc_guard()
+            {
+                if ( !m_pGuard )
+                    m_pGuard = thread_gc::alloc_guard();
+            }
+
+            void free_guard()
             {
             {
-                return Count;
+                if ( m_pGuard ) {
+                    thread_gc::free_guard( m_pGuard );
+                    m_pGuard = nullptr;
+                }
             }
             }
+            //@endcond
+
+        private:
+            //@cond
+            hp::details::hp_guard* m_pGuard;
+            //@endcond
         };
 
     public:
         };
 
     public:
@@ -365,13 +706,13 @@ namespace cds { namespace gc {
             classic = hp::classic,    ///< classic scan as described in Michael's papers
             inplace = hp::inplace     ///< inplace scan without allocation
         };
             classic = hp::classic,    ///< classic scan as described in Michael's papers
             inplace = hp::inplace     ///< inplace scan without allocation
         };
-        /// Initializes hp::GarbageCollector singleton
+        /// Initializes %HP singleton
         /**
             The constructor initializes GC singleton with passed parameters.
             If GC instance is not exist then the function creates the instance.
             Otherwise it does nothing.
 
         /**
             The constructor initializes GC singleton with passed parameters.
             If GC instance is not exist then the function creates the instance.
             Otherwise it does nothing.
 
-            The Michael's HP reclamation schema depends of three parameters:
+            The Michael's %HP reclamation schema depends of three parameters:
             - \p nHazardPtrCount - hazard pointer count per thread. Usually it is small number (up to 10) depending from
                 the data structure algorithms. By default, if \p nHazardPtrCount = 0, the function
                 uses maximum of the hazard pointer count for CDS library.
             - \p nHazardPtrCount - hazard pointer count per thread. Usually it is small number (up to 10) depending from
                 the data structure algorithms. By default, if \p nHazardPtrCount = 0, the function
                 uses maximum of the hazard pointer count for CDS library.
@@ -396,7 +737,9 @@ namespace cds { namespace gc {
 
         /// Terminates GC singleton
         /**
 
         /// Terminates GC singleton
         /**
-            The destructor calls \code hp::GarbageCollector::Destruct( true ) \endcode
+            The destructor destroys %HP global object. After calling of this function you may \b NOT
+            use CDS data structures based on \p %cds::gc::HP.
+            Usually, %HP object is destroyed at the end of your \p main().
         */
         ~HP()
         {
         */
         ~HP()
         {
@@ -405,7 +748,7 @@ namespace cds { namespace gc {
 
         /// Checks if count of hazard pointer is no less than \p nCountNeeded
         /**
 
         /// Checks if count of hazard pointer is no less than \p nCountNeeded
         /**
-            If \p bRaiseException is \p true (that is the default), the function raises 
+            If \p bRaiseException is \p true (that is the default), the function raises
             an \p std::overflow_error exception "Too few hazard pointers"
             if \p nCountNeeded is more than the count of hazard pointer per thread.
         */
             an \p std::overflow_error exception "Too few hazard pointers"
             if \p nCountNeeded is more than the count of hazard pointer per thread.
         */
@@ -420,19 +763,19 @@ namespace cds { namespace gc {
         }
 
         /// Returns max Hazard Pointer count
         }
 
         /// Returns max Hazard Pointer count
-        size_t max_hazard_count() const
+        static size_t max_hazard_count()
         {
             return hp::GarbageCollector::instance().getHazardPointerCount();
         }
 
         /// Returns max count of thread
         {
             return hp::GarbageCollector::instance().getHazardPointerCount();
         }
 
         /// Returns max count of thread
-        size_t max_thread_count() const
+        static size_t max_thread_count()
         {
             return hp::GarbageCollector::instance().getMaxThreadCount();
         }
 
         /// Returns capacity of retired pointer array
         {
             return hp::GarbageCollector::instance().getMaxThreadCount();
         }
 
         /// Returns capacity of retired pointer array
-        size_t retired_array_capacity() const
+        static size_t retired_array_capacity()
         {
             return hp::GarbageCollector::instance().getMaxRetiredPtrCount();
         }
         {
             return hp::GarbageCollector::instance().getMaxRetiredPtrCount();
         }
@@ -444,7 +787,7 @@ namespace cds { namespace gc {
             Deleting the pointer is the function \p pFunc call.
         */
         template <typename T>
             Deleting the pointer is the function \p pFunc call.
         */
         template <typename T>
-        static void retire( T * p, void (* pFunc)(T *) )    ;   // inline in hp_impl.h
+        static void retire( T * p, void (* pFunc)(T *) );   // inline in hp_impl.h
 
         /// Retire pointer \p p with functor of type \p Disposer
         /**
 
         /// Retire pointer \p p with functor of type \p Disposer
         /**
@@ -496,16 +839,16 @@ namespace cds { namespace gc {
             \endcode
         */
         template <class Disposer, typename T>
             \endcode
         */
         template <class Disposer, typename T>
-        static void retire( T * p ) ;   // inline in hp_impl.h
+        static void retire( T * p );   // inline in hp_impl.h
 
         /// Get current scan strategy
 
         /// Get current scan strategy
-        scan_type getScanType() const
+        static scan_type getScanType()
         {
             return static_cast<scan_type>( hp::GarbageCollector::instance().getScanType());
         }
 
         /// Set current scan strategy
         {
             return static_cast<scan_type>( hp::GarbageCollector::instance().getScanType());
         }
 
         /// Set current scan strategy
-        void setScanType(
+        static void setScanType(
             scan_type nScanType     ///< new scan strategy
         )
         {
             scan_type nScanType     ///< new scan strategy
         )
         {
@@ -532,4 +875,4 @@ namespace cds { namespace gc {
     };
 }}  // namespace cds::gc
 
     };
 }}  // namespace cds::gc
 
-#endif  // #ifndef __CDS_GC_IMPL_HP_DECL_H
+#endif  // #ifndef CDSLIB_GC_IMPL_HP_DECL_H