2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
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.
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.
31 #ifndef CDSLIB_URCU_RAW_PTR_H
32 #define CDSLIB_URCU_RAW_PTR_H
34 #include <utility> // std::move
35 #include <type_traits>
36 #include <cds/details/defs.h>
38 namespace cds { namespace urcu {
40 /// Raw pointer to node of RCU-based container
42 This class is intented for returning a pointer to node of RCU-based container.
43 The objects of \p %raw_ptr class is returned by functions like \p get() of that containers.
44 Those functions must be called only under RCU-lock, otherwise the node returned can be reclaimed.
45 On the other hand, traversing the container can remove a lot of nodes marked as deleted ones.
46 Since RCU is locked, such nodes cannot be reclaimed immediately and must be retired only
49 The object of \p %raw_ptr solves that problem: it contains the pointer to the node found
50 and a chain of nodes that were reclaimed during traversing. The \p %raw_ptr object destructor
51 frees the chain (but not the node found) passing it to RCU \p batch_retire().
53 The object of \p %raw_ptr class must be destructed only outside RCU-lock of current thread.
55 Usually, you do not need to use \p %raw_ptr class directly. Each RCU container declares
56 a \p %raw_ptr typedef suitable for the container.
59 - \p RCU - one of \ref cds_urcu_gc "RCU type"
60 - \p ValueType - type of values stored in container
61 - \p ReclaimedEnumerator - implementation-defined for each type of container
63 Example: let \p Container is an RCU container
68 typename Container::raw_ptr pRaw;
72 typename Container::rcu_lock l;
78 // Release outside RCU-lock
85 typename ReclaimedEnumerator
90 typedef RCU rcu; ///< RCU type - one of <tt>cds::urcu::gc< ... ></tt>
91 typedef ValueType value_type; ///< Value type pointed by \p %raw_ptr
92 typedef ReclaimedEnumerator reclaimed_enumerator; ///< implementation-defined, for internal use only
96 value_type * m_ptr; ///< pointer to node
97 reclaimed_enumerator m_Enum; ///< reclaimed node enumerator
101 /// Constructs an empty raw pointer
107 raw_ptr( raw_ptr&& p )
109 , m_Enum(std::move( p.m_Enum ))
114 /// Copy ctor is prohibited
115 raw_ptr( raw_ptr const& ) = delete;
118 // Only for internal use
119 raw_ptr( value_type * p, reclaimed_enumerator&& e )
121 , m_Enum(std::move( e ))
123 raw_ptr( reclaimed_enumerator&& e )
125 , m_Enum(std::move( e ))
129 /// Releases the raw pointer
136 /// Move assignment operator
138 This operator may be called only inside RCU-lock.
139 The \p this should be empty.
141 raw_ptr& operator=( raw_ptr&& p ) CDS_NOEXCEPT
144 if ( !rcu::is_locked() )
148 m_Enum = std::move( p.m_Enum );
153 /// Copy assignment is prohibited
154 raw_ptr& operator=( raw_ptr const& ) = delete;
156 /// Returns a pointer to stored value
157 value_type * operator ->() const CDS_NOEXCEPT
162 /// Returns a reference to stored value
163 value_type& operator *()
165 assert( m_ptr != nullptr );
169 /// Returns a reference to stored value
170 value_type const& operator *() const
172 assert( m_ptr != nullptr );
176 /// Checks if the \p %raw_ptr is \p nullptr
177 bool empty() const CDS_NOEXCEPT
179 return m_ptr == nullptr;
182 /// Checks if the \p %raw_ptr is not empty
183 explicit operator bool() const CDS_NOEXCEPT
188 /// Releases the \p %raw_ptr object
190 This function may be called only outside RCU locked region.
191 After \p %release() the object becomes empty and can be reused.
201 // Adapter of \p raw_ptr for non-intrusive containers based on intrusive counterpart
207 class raw_ptr_adaptor: private RawPtr
210 typedef RawPtr intrusive_raw_ptr;
211 typedef ValueType value_type;
212 typedef typename intrusive_raw_ptr::value_type node_type;
213 typedef Converter converter_type;
216 // Constructs an empty raw pointer
218 : intrusive_raw_ptr()
222 raw_ptr_adaptor( intrusive_raw_ptr&& p )
223 : intrusive_raw_ptr( std::move(p))
227 raw_ptr_adaptor( raw_ptr_adaptor&& p )
228 : intrusive_raw_ptr( std::move(p))
231 // Copy ctor is prohibited
232 raw_ptr_adaptor( raw_ptr_adaptor const& ) = delete;
234 // Releases the raw pointer
241 // Move assignment operator
243 This operator may be called only inside RCU-lock.
244 The \p this should be empty.
246 In general, move assignment is intented for internal use.
248 raw_ptr_adaptor& operator=( raw_ptr_adaptor&& p ) CDS_NOEXCEPT
250 intrusive_raw_ptr::operator =(std::move(p));
254 // Copy assignment is prohibited
255 raw_ptr_adaptor& operator=( raw_ptr_adaptor const& ) = delete;
257 // Returns a pointer to stored value
258 value_type * operator ->() const CDS_NOEXCEPT
260 return converter_type()( intrusive_raw_ptr::operator->());
263 // Returns a reference to stored value
264 value_type& operator *()
266 return converter_type()( intrusive_raw_ptr::operator*());
269 // Returns a reference to stored value
270 value_type const& operator *() const
272 return converter_type()( intrusive_raw_ptr::operator*());
275 // Checks if the \p %raw_ptr is \p nullptr
276 bool empty() const CDS_NOEXCEPT
278 return intrusive_raw_ptr::empty();
281 // Checks if the \p %raw_ptr is not empty
282 explicit operator bool() const CDS_NOEXCEPT
287 // Releases the \p %raw_ptr object
289 This function may be called only outside RCU section.
290 After \p %release() the object can be reused.
294 intrusive_raw_ptr::release();
299 }} // namespace cds::urcu
301 #endif // #ifndef CDSLIB_URCU_RAW_PTR_H