Rebuilt threaded uRCU logic
[libcds.git] / cds / gc / details / retired_ptr.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_GC_DETAILS_RETIRED_PTR_H
4 #define CDSLIB_GC_DETAILS_RETIRED_PTR_H
5
6 #include <cds/details/defs.h>
7 #include <cds/details/static_functor.h>
8
9 //@cond
10 namespace cds { namespace gc {
11     /// Common implementation details for any GC
12     namespace details {
13
14         /// Pointer to function to free (destruct and deallocate) retired pointer of specific type
15         typedef void (* free_retired_ptr_func )( void * );
16
17         /// Retired pointer
18         /**
19             Pointer to an object that is ready to delete.
20         */
21         struct retired_ptr {
22             /// Pointer type
23             typedef void *          pointer;
24
25             union {
26                 pointer                 m_p;        ///< retired pointer
27                 uintptr_t               m_n;
28             };
29             free_retired_ptr_func   m_funcFree; ///< pointer to the destructor function
30
31             /// Comparison of two retired pointers
32             static bool less( const retired_ptr& p1, const retired_ptr& p2 ) CDS_NOEXCEPT
33             {
34                 return p1.m_p < p2.m_p;
35             }
36
37             /// Default ctor initializes pointer to \p nullptr
38             retired_ptr() CDS_NOEXCEPT
39                 : m_p( nullptr )
40                 , m_funcFree( nullptr )
41             {}
42
43             /// Ctor
44             retired_ptr( pointer p, free_retired_ptr_func func ) CDS_NOEXCEPT
45                 : m_p( p )
46                 , m_funcFree( func )
47             {}
48
49             /// Typecasting ctor
50             template <typename T>
51             retired_ptr( T * p, void (* pFreeFunc)(T *)) CDS_NOEXCEPT
52                 : m_p( reinterpret_cast<pointer>(p))
53                 , m_funcFree( reinterpret_cast< free_retired_ptr_func >( pFreeFunc ))
54             {}
55
56             /// Assignment operator
57             retired_ptr& operator =( retired_ptr const& s) CDS_NOEXCEPT
58             {
59                 m_p = s.m_p;
60                 m_funcFree = s.m_funcFree;
61                 return *this;
62             }
63
64             /// Invokes destructor function for the pointer
65             void free()
66             {
67                 assert( m_funcFree );
68                 assert( m_p );
69                 m_funcFree( m_p );
70
71                 CDS_STRICT_DO( clear() );
72             }
73
74             /// Checks if the retired pointer is not empty
75             explicit operator bool() const CDS_NOEXCEPT
76             {
77                 return m_p != nullptr;
78             }
79
80             /// Clears retired pointer without \p free() call
81             void clear()
82             {
83                 m_p = nullptr;
84                 m_funcFree = nullptr;
85             }
86         };
87
88         static inline bool operator <( const retired_ptr& p1, const retired_ptr& p2 ) CDS_NOEXCEPT
89         {
90             return retired_ptr::less( p1, p2 );
91         }
92
93         static inline bool operator ==( const retired_ptr& p1, const retired_ptr& p2 ) CDS_NOEXCEPT
94         {
95             return p1.m_p == p2.m_p;
96         }
97
98         static inline bool operator !=( const retired_ptr& p1, const retired_ptr& p2 ) CDS_NOEXCEPT
99         {
100             return !(p1 == p2);
101         }
102     }  // namespace details
103
104     template <typename Func, typename T>
105     static inline cds::gc::details::retired_ptr make_retired_ptr( T * p )
106     {
107         return cds::gc::details::retired_ptr( p, cds::details::static_functor<Func, T>::call );
108     }
109
110 }}   // namespace cds::gc
111 //@endcond
112
113 #endif // #ifndef CDSLIB_GC_DETAILS_RETIRED_PTR_H