Updated copyright
[libcds.git] / cds / gc / impl / hp_decl.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef CDSLIB_GC_IMPL_HP_DECL_H
32 #define CDSLIB_GC_IMPL_HP_DECL_H
33
34 #include <stdexcept>    // overflow_error
35 #include <cds/gc/details/hp.h>
36 #include <cds/details/marked_ptr.h>
37
38 namespace cds { namespace gc {
39     /// @defgroup cds_garbage_collector Garbage collectors
40
41     /// Hazard Pointer garbage collector
42     /**  @ingroup cds_garbage_collector
43         @headerfile cds/gc/hp.h
44
45         Implementation of classic Hazard Pointer garbage collector.
46
47         Sources:
48             - [2002] Maged M.Michael "Safe memory reclamation for dynamic lock-freeobjects using atomic reads and writes"
49             - [2003] Maged M.Michael "Hazard Pointers: Safe memory reclamation for lock-free objects"
50             - [2004] Andrei Alexandrescy, Maged Michael "Lock-free Data Structures with Hazard Pointers"
51
52         Hazard Pointer garbage collector is a singleton. The main user-level part of Hazard Pointer schema is
53         GC class \p %cds::gc::HP and its nested classes. Before use any HP-related class you must initialize HP garbage collector
54         by contructing \p %cds::gc::HP object in beginning of your \p main().
55         See \ref cds_how_to_use "How to use" section for details how to apply garbage collector.
56     */
57     class HP
58     {
59     public:
60         /// Native guarded pointer type
61         /**
62             @headerfile cds/gc/hp.h
63         */
64         typedef gc::hp::hazard_pointer guarded_pointer;
65
66         /// Atomic reference
67         /**
68             @headerfile cds/gc/hp.h
69         */
70         template <typename T> using atomic_ref = atomics::atomic<T *>;
71
72         /// Atomic marked pointer
73         /**
74             @headerfile cds/gc/hp.h
75         */
76         template <typename MarkedPtr> using atomic_marked_ptr = atomics::atomic<MarkedPtr>;
77
78         /// Atomic type
79         /**
80             @headerfile cds/gc/hp.h
81         */
82         template <typename T> using atomic_type = atomics::atomic<T>;
83
84         /// Thread GC implementation for internal usage
85         /**
86             @headerfile cds/gc/hp.h
87         */
88         typedef hp::ThreadGC   thread_gc_impl;
89
90         /// Exception "Too many Hazard Pointer"
91         typedef hp::GarbageCollector::too_many_hazard_ptr too_many_hazard_ptr_exception;
92
93         /// Wrapper for hp::ThreadGC class
94         /**
95             @headerfile cds/gc/hp.h
96             This class performs automatically attaching/detaching Hazard Pointer GC
97             for the current thread.
98         */
99         class thread_gc: public thread_gc_impl
100         {
101             //@cond
102             bool    m_bPersistent;
103             //@endcond
104         public:
105
106             /// Constructor
107             /**
108                 The constructor attaches the current thread to the Hazard Pointer GC
109                 if it is not yet attached.
110                 The \p bPersistent parameter specifies attachment persistence:
111                 - \p true - the class destructor will not detach the thread from Hazard Pointer GC.
112                 - \p false (default) - the class destructor will detach the thread from Hazard Pointer GC.
113             */
114             thread_gc(
115                 bool    bPersistent = false
116             ) ;     //inline in hp_impl.h
117
118             /// Destructor
119             /**
120                 If the object has been created in persistent mode, the destructor does nothing.
121                 Otherwise it detaches the current thread from Hazard Pointer GC.
122             */
123             ~thread_gc() ;  // inline in hp_impl.h
124
125         public: // for internal use only!!!
126             //@cond
127             static cds::gc::hp::details::hp_guard* alloc_guard(); // inline in hp_impl.h
128             static void free_guard( cds::gc::hp::details::hp_guard* g ); // inline in hp_impl.h
129             //@endcond
130         };
131
132         /// Hazard Pointer guard
133         /**
134             @headerfile cds/gc/hp.h
135
136             A guard is a hazard pointer.
137             Additionally, the \p %Guard class manages allocation and deallocation of the hazard pointer.
138
139             \p %Guard object is movable but not copyable.
140
141             The guard object can be in two states:
142             - unlinked - the guard is not linked with any internal hazard pointer.
143               In this state no operation except \p link() and move assignment is supported.
144             - linked (default) - the guard allocates an internal hazard pointer and fully operable.
145
146             Due to performance reason the implementation does not check state of the guard in runtime.
147
148             @warning Move assignment can transfer the guard in unlinked state, use with care.
149         */
150         class Guard
151         {
152         public:
153             /// Default ctor allocates a guard (hazard pointer) from thread-private storage
154             /**
155                 @warning Can throw \p too_many_hazard_ptr_exception if internal hazard pointer objects are exhausted.
156             */
157             Guard();  // inline in hp_impl.h
158
159             /// Initilalizes an unlinked guard i.e. the guard contains no hazard pointer. Used for move semantics support
160             explicit Guard( std::nullptr_t ) CDS_NOEXCEPT
161                 : m_guard( nullptr )
162             {}
163
164             /// Move ctor - \p src guard becomes unlinked (transfer internal guard ownership)
165             Guard( Guard&& src ) CDS_NOEXCEPT
166                 : m_guard( src.m_guard )
167             {
168                 src.m_guard = nullptr;
169             }
170
171             /// Move assignment: the internal guards are swapped between \p src and \p this
172             /**
173                 @warning \p src will become in unlinked state if \p this was unlinked on entry.
174             */
175             Guard& operator=( Guard&& src ) CDS_NOEXCEPT
176             {
177                 std::swap( m_guard, src.m_guard );
178                 return *this;
179             }
180
181             /// Copy ctor is prohibited - the guard is not copyable
182             Guard( Guard const& ) = delete;
183
184             /// Copy assignment is prohibited
185             Guard& operator=( Guard const& ) = delete;
186
187             /// Frees the internal hazard pointer if the guard is in linked state
188             ~Guard()
189             {
190                 unlink();
191             }
192
193             /// Checks if the guard object linked with any internal hazard pointer
194             bool is_linked() const
195             {
196                 return m_guard != nullptr;
197             }
198
199             /// Links the guard with internal hazard pointer if the guard is in unlinked state
200             /**
201                 @warning Can throw \p too_many_hazard_ptr_exception if internal hazard pointer objects are exhausted.
202             */
203             void link(); // inline in hp_impl.h
204
205             /// Unlinks the guard from internal hazard pointer; the guard becomes in unlinked state
206             void unlink(); // inline in hp_impl.h
207
208             /// Protects a pointer of type \p atomic<T*>
209             /**
210                 Return the value of \p toGuard
211
212                 The function tries to load \p toGuard and to store it
213                 to the HP slot repeatedly until the guard's value equals \p toGuard
214
215                 @warning The guad object should be in linked state, otherwise the result is undefined
216             */
217             template <typename T>
218             T protect( atomics::atomic<T> const& toGuard )
219             {
220                 assert( m_guard != nullptr );
221
222                 T pCur = toGuard.load(atomics::memory_order_acquire);
223                 T pRet;
224                 do {
225                     pRet = assign( pCur );
226                     pCur = toGuard.load(atomics::memory_order_acquire);
227                 } while ( pRet != pCur );
228                 return pCur;
229             }
230
231             /// Protects a converted pointer of type \p atomic<T*>
232             /**
233                 Return the value of \p toGuard
234
235                 The function tries to load \p toGuard and to store result of \p f functor
236                 to the HP slot repeatedly until the guard's value equals \p toGuard.
237
238                 The function is useful for intrusive containers when \p toGuard is a node pointer
239                 that should be converted to a pointer to the value before protecting.
240                 The parameter \p f of type Func is a functor that makes this conversion:
241                 \code
242                     struct functor {
243                         value_type * operator()( T * p );
244                     };
245                 \endcode
246                 Actually, the result of <tt> f( toGuard.load()) </tt> is assigned to the hazard pointer.
247
248                 @warning The guad object should be in linked state, otherwise the result is undefined
249             */
250             template <typename T, class Func>
251             T protect( atomics::atomic<T> const& toGuard, Func f )
252             {
253                 assert( m_guard != nullptr );
254
255                 T pCur = toGuard.load(atomics::memory_order_acquire);
256                 T pRet;
257                 do {
258                     pRet = pCur;
259                     assign( f( pCur ));
260                     pCur = toGuard.load(atomics::memory_order_acquire);
261                 } while ( pRet != pCur );
262                 return pCur;
263             }
264
265             /// Store \p p to the guard
266             /**
267                 The function equals to a simple assignment the value \p p to guard, no loop is performed.
268                 Can be used for a pointer that cannot be changed concurrently
269
270                 @warning The guad object should be in linked state, otherwise the result is undefined
271             */
272             template <typename T>
273             T * assign( T* p );    // inline in hp_impl.h
274
275             //@cond
276             std::nullptr_t assign( std::nullptr_t )
277             {
278                 assert(m_guard != nullptr );
279                 return *m_guard = nullptr;
280             }
281             //@endcond
282
283             /// Copy a value guarded from \p src guard to \p this guard (valid only in linked state)
284             void copy( Guard const& src )
285             {
286                 assign( src.get_native());
287             }
288
289             /// Store marked pointer \p p to the guard
290             /**
291                 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
292                 Can be used for a marked pointer that cannot be changed concurrently.
293
294                 @warning The guad object should be in linked state, otherwise the result is undefined
295             */
296             template <typename T, int BITMASK>
297             T * assign( cds::details::marked_ptr<T, BITMASK> p )
298             {
299                 return assign( p.ptr());
300             }
301
302             /// Clear value of the guard (valid only in linked state)
303             void clear()
304             {
305                 assign( nullptr );
306             }
307
308             /// Get the value currently protected (valid only in linked state)
309             template <typename T>
310             T * get() const
311             {
312                 return reinterpret_cast<T *>( get_native());
313             }
314
315             /// Get native hazard pointer stored (valid only in linked state)
316             guarded_pointer get_native() const
317             {
318                 assert( m_guard != nullptr );
319                 return m_guard->get();
320             }
321
322             //@cond
323             hp::details::hp_guard* release()
324             {
325                 hp::details::hp_guard* g = m_guard;
326                 m_guard = nullptr;
327                 return g;
328             }
329
330             hp::details::hp_guard*& guard_ref()
331             {
332                 return m_guard;
333             }
334             //@endcond
335
336         private:
337             //@cond
338             hp::details::hp_guard* m_guard;
339             //@endcond
340         };
341
342         /// Array of Hazard Pointer guards
343         /**
344             @headerfile cds/gc/hp.h
345             The class is intended for allocating an array of hazard pointer guards.
346             Template parameter \p Count defines the size of the array.
347
348         */
349         template <size_t Count>
350         class GuardArray
351         {
352         public:
353             /// Rebind array for other size \p Count2
354             template <size_t Count2>
355             struct rebind {
356                 typedef GuardArray<Count2>  other;   ///< rebinding result
357             };
358
359             /// Array capacity
360             static CDS_CONSTEXPR const size_t c_nCapacity = Count;
361
362         public:
363             /// Default ctor allocates \p Count hazard pointers
364             GuardArray(); // inline in hp_impl.h
365
366             /// Move ctor is prohibited
367             GuardArray( GuardArray&& ) = delete;
368
369             /// Move assignment is prohibited
370             GuardArray& operator=( GuardArray&& ) = delete;
371
372             /// Copy ctor is prohibited
373             GuardArray( GuardArray const& ) = delete;
374
375             /// Copy assignment is prohibited
376             GuardArray& operator=( GuardArray const& ) = delete;
377
378             /// Frees allocated hazard pointers
379             ~GuardArray(); // inline in hp_impl.h
380
381             /// Protects a pointer of type \p atomic<T*>
382             /**
383                 Return the value of \p toGuard
384
385                 The function tries to load \p toGuard and to store it
386                 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
387             */
388             template <typename T>
389             T protect( size_t nIndex, atomics::atomic<T> const& toGuard )
390             {
391                 assert( nIndex < capacity());
392
393                 T pRet;
394                 do {
395                     pRet = assign( nIndex, toGuard.load(atomics::memory_order_acquire));
396                 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
397
398                 return pRet;
399             }
400
401             /// Protects a pointer of type \p atomic<T*>
402             /**
403                 Return the value of \p toGuard
404
405                 The function tries to load \p toGuard and to store it
406                 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
407
408                 The function is useful for intrusive containers when \p toGuard is a node pointer
409                 that should be converted to a pointer to the value type before guarding.
410                 The parameter \p f of type Func is a functor that makes this conversion:
411                 \code
412                     struct functor {
413                         value_type * operator()( T * p );
414                     };
415                 \endcode
416                 Really, the result of <tt> f( toGuard.load()) </tt> is assigned to the hazard pointer.
417             */
418             template <typename T, class Func>
419             T protect( size_t nIndex, atomics::atomic<T> const& toGuard, Func f )
420             {
421                 assert( nIndex < capacity());
422
423                 T pRet;
424                 do {
425                     assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_acquire)));
426                 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
427
428                 return pRet;
429             }
430
431             /// Store \p to the slot \p nIndex
432             /**
433                 The function equals to a simple assignment, no loop is performed.
434             */
435             template <typename T>
436             T * assign( size_t nIndex, T * p ); // inline in hp_impl.h
437
438             /// Store marked pointer \p p to the guard
439             /**
440                 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
441                 Can be used for a marked pointer that cannot be changed concurrently.
442             */
443             template <typename T, int BITMASK>
444             T * assign( size_t nIndex, cds::details::marked_ptr<T, BITMASK> p )
445             {
446                 return assign( nIndex, p.ptr());
447             }
448
449             /// Copy guarded value from \p src guard to slot at index \p nIndex
450             void copy( size_t nIndex, Guard const& src )
451             {
452                 assign( nIndex, src.get_native());
453             }
454
455             /// Copy guarded value from slot \p nSrcIndex to the slot \p nDestIndex
456             void copy( size_t nDestIndex, size_t nSrcIndex )
457             {
458                 assign( nDestIndex, get_native( nSrcIndex ));
459             }
460
461             /// Clear value of the slot \p nIndex
462             void clear( size_t nIndex )
463             {
464                 m_arr.clear( nIndex );
465             }
466
467             /// Get current value of slot \p nIndex
468             template <typename T>
469             T * get( size_t nIndex ) const
470             {
471                 return reinterpret_cast<T *>( get_native( nIndex ));
472             }
473
474             /// Get native hazard pointer stored
475             guarded_pointer get_native( size_t nIndex ) const
476             {
477                 assert( nIndex < capacity());
478                 return m_arr[nIndex]->get();
479             }
480
481             //@cond
482             hp::details::hp_guard* release( size_t nIndex ) CDS_NOEXCEPT
483             {
484                 return m_arr.release( nIndex );
485             }
486             //@endcond
487
488             /// Capacity of the guard array
489             static CDS_CONSTEXPR size_t capacity()
490             {
491                 return c_nCapacity;
492             }
493
494         private:
495             //@cond
496             hp::details::hp_array<Count> m_arr;
497             //@endcond
498         };
499
500         /// Guarded pointer
501         /**
502             A guarded pointer is a pair of a pointer and GC's guard.
503             Usually, it is used for returning a pointer to the item from an lock-free container.
504             The guard prevents the pointer to be early disposed (freed) by GC.
505             After destructing \p %guarded_ptr object the pointer can be disposed (freed) automatically at any time.
506
507             Template arguments:
508             - \p GuardedType - a type which the guard stores
509             - \p ValueType - a value type
510             - \p Cast - a functor for converting <tt>GuardedType*</tt> to <tt>ValueType*</tt>. Default is \p void (no casting).
511
512             For intrusive containers, \p GuardedType is the same as \p ValueType and no casting is needed.
513             In such case the \p %guarded_ptr is:
514             @code
515             typedef cds::gc::HP::guarded_ptr< foo > intrusive_guarded_ptr;
516             @endcode
517
518             For standard (non-intrusive) containers \p GuardedType is not the same as \p ValueType and casting is needed.
519             For example:
520             @code
521             struct foo {
522                 int const   key;
523                 std::string value;
524             };
525
526             struct value_accessor {
527                 std::string* operator()( foo* pFoo ) const
528                 {
529                     return &(pFoo->value);
530                 }
531             };
532
533             // Guarded ptr
534             typedef cds::gc::HP::guarded_ptr< Foo, std::string, value_accessor > nonintrusive_guarded_ptr;
535             @endcode
536
537             You don't need use this class directly.
538             All set/map container classes from \p libcds declare the typedef for \p %guarded_ptr with appropriate casting functor.
539         */
540         template <typename GuardedType, typename ValueType=GuardedType, typename Cast=void >
541         class guarded_ptr
542         {
543             //@cond
544             struct trivial_cast {
545                 ValueType * operator()( GuardedType * p ) const
546                 {
547                     return p;
548                 }
549             };
550
551             template <typename GT, typename VT, typename C> friend class guarded_ptr;
552             //@endcond
553
554         public:
555             typedef GuardedType guarded_type; ///< Guarded type
556             typedef ValueType   value_type;   ///< Value type
557
558             /// Functor for casting \p guarded_type to \p value_type
559             typedef typename std::conditional< std::is_same<Cast, void>::value, trivial_cast, Cast >::type value_cast;
560
561         public:
562             /// Creates empty guarded pointer
563             guarded_ptr() CDS_NOEXCEPT
564                 : m_pGuard(nullptr)
565             {}
566
567             //@cond
568             explicit guarded_ptr( hp::details::hp_guard* g ) CDS_NOEXCEPT
569                 : m_pGuard( g )
570             {}
571
572             /// Initializes guarded pointer with \p p
573             explicit guarded_ptr( guarded_type* p ) CDS_NOEXCEPT
574                 : m_pGuard( nullptr )
575             {
576                 reset(p);
577             }
578             explicit guarded_ptr( std::nullptr_t ) CDS_NOEXCEPT
579                 : m_pGuard( nullptr )
580             {}
581             //@endcond
582
583             /// Move ctor
584             guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
585                 : m_pGuard( gp.m_pGuard )
586             {
587                 gp.m_pGuard = nullptr;
588             }
589
590             /// Move ctor
591             template <typename GT, typename VT, typename C>
592             guarded_ptr( guarded_ptr<GT, VT, C>&& gp ) CDS_NOEXCEPT
593                 : m_pGuard( gp.m_pGuard )
594             {
595                 gp.m_pGuard = nullptr;
596             }
597
598             /// Ctor from \p Guard
599             explicit guarded_ptr( Guard&& g ) CDS_NOEXCEPT
600                 : m_pGuard( g.release())
601             {}
602
603             /// The guarded pointer is not copy-constructible
604             guarded_ptr( guarded_ptr const& gp ) = delete;
605
606             /// Clears the guarded pointer
607             /**
608                 \ref release() is called if guarded pointer is not \ref empty()
609             */
610             ~guarded_ptr() CDS_NOEXCEPT
611             {
612                 release();
613             }
614
615             /// Move-assignment operator
616             guarded_ptr& operator=( guarded_ptr&& gp ) CDS_NOEXCEPT
617             {
618                 std::swap( m_pGuard, gp.m_pGuard );
619                 return *this;
620             }
621
622             /// Move-assignment from \p Guard
623             guarded_ptr& operator=( Guard&& g ) CDS_NOEXCEPT
624             {
625                 std::swap( m_pGuard, g.guard_ref());
626                 return *this;
627             }
628
629             /// The guarded pointer is not copy-assignable
630             guarded_ptr& operator=(guarded_ptr const& gp) = delete;
631
632             /// Returns a pointer to guarded value
633             value_type * operator ->() const CDS_NOEXCEPT
634             {
635                 assert( !empty());
636                 return value_cast()( reinterpret_cast<guarded_type *>(m_pGuard->get()));
637             }
638
639             /// Returns a reference to guarded value
640             value_type& operator *() CDS_NOEXCEPT
641             {
642                 assert( !empty());
643                 return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
644             }
645
646             /// Returns const reference to guarded value
647             value_type const& operator *() const CDS_NOEXCEPT
648             {
649                 assert( !empty());
650                 return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
651             }
652
653             /// Checks if the guarded pointer is \p nullptr
654             bool empty() const CDS_NOEXCEPT
655             {
656                 return !m_pGuard || m_pGuard->get( atomics::memory_order_relaxed ) == nullptr;
657             }
658
659             /// \p bool operator returns <tt>!empty()</tt>
660             explicit operator bool() const CDS_NOEXCEPT
661             {
662                 return !empty();
663             }
664
665             /// Clears guarded pointer
666             /**
667                 If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
668                 Dereferncing the guarded pointer after \p release() is dangerous.
669             */
670             void release() CDS_NOEXCEPT
671             {
672                 free_guard();
673             }
674
675             //@cond
676             // For internal use only!!!
677             void reset(guarded_type * p) CDS_NOEXCEPT
678             {
679                 alloc_guard();
680                 assert( m_pGuard );
681                 m_pGuard->set(p);
682             }
683             //@endcond
684
685         private:
686             //@cond
687             void alloc_guard()
688             {
689                 if ( !m_pGuard )
690                     m_pGuard = thread_gc::alloc_guard();
691             }
692
693             void free_guard()
694             {
695                 if ( m_pGuard ) {
696                     thread_gc::free_guard( m_pGuard );
697                     m_pGuard = nullptr;
698                 }
699             }
700             //@endcond
701
702         private:
703             //@cond
704             hp::details::hp_guard* m_pGuard;
705             //@endcond
706         };
707
708     public:
709         /// \p scan() type
710         enum class scan_type {
711             classic = hp::classic,    ///< classic scan as described in Michael's papers
712             inplace = hp::inplace     ///< inplace scan without allocation
713         };
714         /// Initializes %HP singleton
715         /**
716             The constructor initializes GC singleton with passed parameters.
717             If GC instance is not exist then the function creates the instance.
718             Otherwise it does nothing.
719
720             The Michael's %HP reclamation schema depends of three parameters:
721             - \p nHazardPtrCount - hazard pointer count per thread. Usually it is small number (up to 10) depending from
722                 the data structure algorithms. By default, if \p nHazardPtrCount = 0, the function
723                 uses maximum of the hazard pointer count for CDS library.
724             - \p nMaxThreadCount - max count of thread with using Hazard Pointer GC in your application. Default is 100.
725             - \p nMaxRetiredPtrCount - capacity of array of retired pointers for each thread. Must be greater than
726                 <tt> nHazardPtrCount * nMaxThreadCount </tt>. Default is <tt>2 * nHazardPtrCount * nMaxThreadCount </tt>.
727         */
728         HP(
729             size_t nHazardPtrCount = 0,     ///< Hazard pointer count per thread
730             size_t nMaxThreadCount = 0,     ///< Max count of simultaneous working thread in your application
731             size_t nMaxRetiredPtrCount = 0, ///< Capacity of the array of retired objects for the thread
732             scan_type nScanType = scan_type::inplace   ///< Scan type (see \p scan_type enum)
733         )
734         {
735             hp::GarbageCollector::Construct(
736                 nHazardPtrCount,
737                 nMaxThreadCount,
738                 nMaxRetiredPtrCount,
739                 static_cast<hp::scan_type>(nScanType)
740             );
741         }
742
743         /// Terminates GC singleton
744         /**
745             The destructor destroys %HP global object. After calling of this function you may \b NOT
746             use CDS data structures based on \p %cds::gc::HP.
747             Usually, %HP object is destroyed at the end of your \p main().
748         */
749         ~HP()
750         {
751             hp::GarbageCollector::Destruct( true );
752         }
753
754         /// Checks if count of hazard pointer is no less than \p nCountNeeded
755         /**
756             If \p bRaiseException is \p true (that is the default), the function raises
757             an \p std::overflow_error exception "Too few hazard pointers"
758             if \p nCountNeeded is more than the count of hazard pointer per thread.
759         */
760         static bool check_available_guards( size_t nCountNeeded, bool bRaiseException = true )
761         {
762             if ( hp::GarbageCollector::instance().getHazardPointerCount() < nCountNeeded ) {
763                 if ( bRaiseException )
764                     throw std::overflow_error( "Too few hazard pointers" );
765                 return false;
766             }
767             return true;
768         }
769
770         /// Returns max Hazard Pointer count
771         static size_t max_hazard_count()
772         {
773             return hp::GarbageCollector::instance().getHazardPointerCount();
774         }
775
776         /// Returns max count of thread
777         static size_t max_thread_count()
778         {
779             return hp::GarbageCollector::instance().getMaxThreadCount();
780         }
781
782         /// Returns capacity of retired pointer array
783         static size_t retired_array_capacity()
784         {
785             return hp::GarbageCollector::instance().getMaxRetiredPtrCount();
786         }
787
788         /// Retire pointer \p p with function \p pFunc
789         /**
790             The function places pointer \p p to array of pointers ready for removing.
791             (so called retired pointer array). The pointer can be safely removed when no hazard pointer points to it.
792             Deleting the pointer is the function \p pFunc call.
793         */
794         template <typename T>
795         static void retire( T * p, void (* pFunc)(T *));   // inline in hp_impl.h
796
797         /// Retire pointer \p p with functor of type \p Disposer
798         /**
799             The function places pointer \p p to array of pointers ready for removing.
800             (so called retired pointer array). The pointer can be safely removed when no hazard pointer points to it.
801
802             Deleting the pointer is an invocation of some object of type \p Disposer; the interface of \p Disposer is:
803             \code
804             template <typename T>
805             struct disposer {
806                 void operator()( T * p )    ;   // disposing operator
807             };
808             \endcode
809             Since the functor call can happen at any time after \p retire call, additional restrictions are imposed to \p Disposer type:
810             - it should be stateless functor
811             - it should be default-constructible
812             - the result of functor call with argument \p p should not depend on where the functor will be called.
813
814             \par Examples:
815             Operator \p delete functor:
816             \code
817             template <typename T>
818             struct disposer {
819                 void operator ()( T * p ) {
820                     delete p;
821                 }
822             };
823
824             // How to call GC::retire method
825             int * p = new int;
826
827             // ... use p in lock-free manner
828
829             cds::gc::HP::retire<disposer>( p ) ;   // place p to retired pointer array of HP GC
830             \endcode
831
832             Functor based on \p std::allocator :
833             \code
834             template <typename ALLOC = std::allocator<int> >
835             struct disposer {
836                 template <typename T>
837                 void operator()( T * p ) {
838                     typedef typename ALLOC::templare rebind<T>::other   alloc_t;
839                     alloc_t a;
840                     a.destroy( p );
841                     a.deallocate( p, 1 );
842                 }
843             };
844             \endcode
845         */
846         template <class Disposer, typename T>
847         static void retire( T * p );   // inline in hp_impl.h
848
849         /// Get current scan strategy
850         static scan_type getScanType()
851         {
852             return static_cast<scan_type>( hp::GarbageCollector::instance().getScanType());
853         }
854
855         /// Set current scan strategy
856         static void setScanType(
857             scan_type nScanType     ///< new scan strategy
858         )
859         {
860             hp::GarbageCollector::instance().setScanType( static_cast<hp::scan_type>(nScanType));
861         }
862
863         /// Checks if Hazard Pointer GC is constructed and may be used
864         static bool isUsed()
865         {
866             return hp::GarbageCollector::isUsed();
867         }
868
869         /// Forced GC cycle call for current thread
870         /**
871             Usually, this function should not be called directly.
872         */
873         static void scan()  ;   // inline in hp_impl.h
874
875         /// Synonym for \ref scan()
876         static void force_dispose()
877         {
878             scan();
879         }
880     };
881 }}  // namespace cds::gc
882
883 #endif  // #ifndef CDSLIB_GC_IMPL_HP_DECL_H