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 be 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.
140 raw_ptr& operator=( raw_ptr&& p ) CDS_NOEXCEPT
142 assert( rcu::is_locked());
144 m_Enum.combine( std::move( p.m_Enum ));
149 /// Copy assignment is prohibited
150 raw_ptr& operator=( raw_ptr const& ) = delete;
152 /// Returns a pointer to stored value
153 value_type * operator ->() const CDS_NOEXCEPT
158 /// Returns a reference to stored value
159 value_type& operator *()
161 assert( m_ptr != nullptr );
165 /// Returns a reference to stored value
166 value_type const& operator *() const
168 assert( m_ptr != nullptr );
172 /// Checks if the \p %raw_ptr is \p nullptr
173 bool empty() const CDS_NOEXCEPT
175 return m_ptr == nullptr;
178 /// Checks if the \p %raw_ptr is not empty
179 explicit operator bool() const CDS_NOEXCEPT
184 /// Releases the \p %raw_ptr object
186 This function may be called only outside RCU locked region.
187 After \p %release() the object becomes empty and can be reused.
197 // Adapter of \p raw_ptr for non-intrusive containers based on intrusive counterpart
203 class raw_ptr_adaptor: private RawPtr
206 typedef RawPtr intrusive_raw_ptr;
207 typedef ValueType value_type;
208 typedef typename intrusive_raw_ptr::value_type node_type;
209 typedef Converter converter_type;
212 // Constructs an empty raw pointer
214 : intrusive_raw_ptr()
218 raw_ptr_adaptor( intrusive_raw_ptr&& p )
219 : intrusive_raw_ptr( std::move(p))
223 raw_ptr_adaptor( raw_ptr_adaptor&& p )
224 : intrusive_raw_ptr( std::move(p))
227 // Copy ctor is prohibited
228 raw_ptr_adaptor( raw_ptr_adaptor const& ) = delete;
230 // Releases the raw pointer
237 // Move assignment operator
239 This operator may be called only inside RCU-lock.
240 The \p this should be empty.
242 In general, move assignment is intented for internal use.
244 raw_ptr_adaptor& operator=( raw_ptr_adaptor&& p ) CDS_NOEXCEPT
246 intrusive_raw_ptr::operator =(std::move(p));
250 // Copy assignment is prohibited
251 raw_ptr_adaptor& operator=( raw_ptr_adaptor const& ) = delete;
253 // Returns a pointer to stored value
254 value_type * operator ->() const CDS_NOEXCEPT
256 return converter_type()( intrusive_raw_ptr::operator->());
259 // Returns a reference to stored value
260 value_type& operator *()
262 return converter_type()( intrusive_raw_ptr::operator*());
265 // Returns a reference to stored value
266 value_type const& operator *() const
268 return converter_type()( intrusive_raw_ptr::operator*());
271 // Checks if the \p %raw_ptr is \p nullptr
272 bool empty() const CDS_NOEXCEPT
274 return intrusive_raw_ptr::empty();
277 // Checks if the \p %raw_ptr is not empty
278 explicit operator bool() const CDS_NOEXCEPT
283 // Releases the \p %raw_ptr object
285 This function may be called only outside RCU section.
286 After \p %release() the object can be reused.
290 intrusive_raw_ptr::release();
295 }} // namespace cds::urcu
297 #endif // #ifndef CDSLIB_URCU_RAW_PTR_H