Move libcds 1.6.0 from SVN
[libcds.git] / cds / gc / guarded_ptr.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_GC_GUARDED_PTR_H
4 #define __CDS_GC_GUARDED_PTR_H
5
6 #include <cds/details/defs.h>
7
8 namespace cds { namespace gc {
9
10     /// Guarded pointer
11     /**
12         A guarded pointer is a pair of the pointer and GC's guard.
13         Usually, it is used for returning a pointer to the item from an lock-free container.
14         The guard prevents the pointer to be early disposed (freed) by GC.
15         After destructing \p %guarded_ptr object the pointer can be automatically disposed (freed) at any time.
16
17         Template arguments:
18         - \p GC - a garbage collector type like cds::gc::HP and any other from cds::gc namespace
19         - \p GuardedType - a type which the guard stores
20         - \p ValueType - a value type
21         - \p Cast - a functor for converting <tt>GuardedType*</tt> to <tt>ValueType*</tt>. Default is \p void (no casting).
22
23         For intrusive containers, \p GuardedType is the same as \p ValueType and no casting is needed.
24         In such case the \p %guarded_ptr is:
25         @code
26         typedef cds::gc::guarded_ptr< cds::gc::HP, foo > intrusive_guarded_ptr;
27         @endcode
28
29         For standard (non-intrusive) containers \p GuardedType is not the same as \p ValueType and casting is needed.
30         For example:
31         @code
32         struct foo {
33             int const   key;
34             std::string value;
35         };
36
37         struct value_accessor {
38             std::string* operator()( foo* pFoo ) const
39             {
40                 return &(pFoo->value);
41             }
42         };
43
44         // Guarded ptr
45         typedef cds::gc::guarded_ptr< cds::gc::HP, Foo, std::string, value_accessor > nonintrusive_guarded_ptr;
46         @endcode
47
48         Many set/map container classes from \p libcds declare the typedef for \p %guarded_ptr with appropriate casting functor.
49     */
50     template <class GC, typename GuardedType, typename ValueType=GuardedType, typename Cast=void >
51     class guarded_ptr
52     {
53         //TODO: use moce semantics and explicit operator bool!
54     public:
55         typedef GC          gc         ;   ///< Garbage collector like cds::gc::HP and any other from cds::gc namespace
56         typedef GuardedType guarded_type;  ///< Guarded type
57         typedef ValueType   value_type ;   ///< Value type
58         typedef Cast        value_cast ;   ///< Functor for casting \p guarded_type to \p value_type
59
60     private:
61         //@cond
62         typename gc::Guard  m_guard;
63         //@endcond
64
65     public:
66         /// Creates empty guarded pointer
67         guarded_ptr() CDS_NOEXCEPT
68         {}
69
70         /// Initializes guarded pointer with \p p
71         guarded_ptr( guarded_type * p ) CDS_NOEXCEPT
72         {
73             m_guard.assign( p );
74         }
75
76         /// Copy constructor
77         guarded_ptr( guarded_ptr const& gp ) CDS_NOEXCEPT
78         {
79             m_guard.copy( gp.m_guard );
80         }
81
82         /// Clears the guarded pointer
83         /**
84             \ref release is called if guarded pointer is not \ref empty
85         */
86         ~guarded_ptr() CDS_NOEXCEPT
87         {
88             release();
89         }
90
91         /// Assignment operator
92         guarded_ptr& operator=( guarded_ptr const& gp ) CDS_NOEXCEPT
93         {
94             m_guard.copy( gp.m_guard );
95             return *this;
96         }
97
98         /// Returns a pointer to guarded value
99         value_type * operator ->() const CDS_NOEXCEPT
100         {
101             return value_cast()( m_guard.template get<guarded_type>() );
102         }
103
104         /// Returns a reference to guarded value
105         value_type& operator *() CDS_NOEXCEPT
106         {
107             assert( !empty());
108             return *value_cast()( m_guard.template get<guarded_type>() );
109         }
110
111         /// Returns const reference to guarded value
112         value_type const& operator *() const CDS_NOEXCEPT
113         {
114             assert( !empty());
115             return *value_cast()( m_guard.template get<guarded_type>() );
116         }
117
118         /// Checks if the guarded pointer is \p NULL
119         bool empty() const CDS_NOEXCEPT
120         {
121             return m_guard.template get<guarded_type>() == null_ptr<guarded_type *>();
122         }
123
124         /// Clears guarded pointer
125         /**
126             If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
127             Dereferncing the guarded pointer after \p release() is dangerous.
128         */
129         void release() CDS_NOEXCEPT
130         {
131             m_guard.clear();
132         }
133
134         //@cond
135         // For internal use only!!!
136         typename gc::Guard& guard() CDS_NOEXCEPT
137         {
138             return m_guard;
139         }
140         //@endcond
141     };
142
143
144     //@cond
145     // Intrusive specialization
146     template <class GC, typename T>
147     class guarded_ptr< GC, T, T, void >
148     {
149     public:
150         typedef GC  gc         ;   ///< Garbage collector like cds::gc::HP
151         typedef T   guarded_type;  ///< Guarded type
152         typedef T   value_type ;   ///< Value type
153
154     private:
155         typename gc::Guard  m_guard;
156
157     public:
158         guarded_ptr() CDS_NOEXCEPT
159         {}
160
161         guarded_ptr( value_type * p ) CDS_NOEXCEPT
162         {
163             m_guard.assign( p );
164         }
165
166         guarded_ptr( guarded_ptr const& gp ) CDS_NOEXCEPT
167         {
168             m_guard.copy( gp.m_guard );
169         }
170
171         ~guarded_ptr() CDS_NOEXCEPT
172         {
173             release();
174         }
175
176         guarded_ptr& operator=( guarded_ptr const& gp ) CDS_NOEXCEPT
177         {
178             m_guard.copy( gp.m_guard );
179             return *this;
180         }
181
182         value_type * operator ->() const CDS_NOEXCEPT
183         {
184             return m_guard.template get<value_type>();
185         }
186
187         value_type& operator *() CDS_NOEXCEPT
188         {
189             assert( !empty());
190             return *m_guard.template get<value_type>();
191         }
192
193         value_type const& operator *() const CDS_NOEXCEPT
194         {
195             assert( !empty());
196             return *m_guard.template get<value_type>();
197         }
198
199         bool empty() const CDS_NOEXCEPT
200         {
201             return m_guard.template get<guarded_type>() == null_ptr<guarded_type *>();
202         }
203
204         void release() CDS_NOEXCEPT
205         {
206             m_guard.clear();
207         }
208
209         typename gc::Guard& guard() CDS_NOEXCEPT
210         {
211             return m_guard;
212         }
213     };
214     //@endcond
215
216 }} // namespace cds::gc
217
218 #endif // #ifndef __CDS_GC_GUARDED_PTR_H