public:
/// Guarded pointer
- typedef cds::gc::guarded_ptr< gc, leaf_node, value_type, details::guarded_ptr_cast_set<leaf_node, value_type> > guarded_ptr;
+ typedef typename gc::template guarded_ptr< leaf_node, value_type, details::guarded_ptr_cast_set<leaf_node, value_type> > guarded_ptr;
public:
/// Default constructor
public:
/// Guarded pointer
- typedef cds::gc::guarded_ptr< gc, leaf_node, value_type, details::guarded_ptr_cast_set<leaf_node, value_type> > guarded_ptr;
+ typedef typename gc::template guarded_ptr< leaf_node, value_type, details::guarded_ptr_cast_set<leaf_node, value_type> > guarded_ptr;
public:
/// Default constructor
#ifndef __CDS_CONTAINER_IMPL_SKIP_LIST_MAP_H
#define __CDS_CONTAINER_IMPL_SKIP_LIST_MAP_H
-#include <cds/gc/guarded_ptr.h>
#include <cds/container/details/guarded_ptr_cast.h>
namespace cds { namespace container {
#define __CDS_CONTAINER_IMPL_SKIP_LIST_SET_H
#include <cds/details/binary_functor_wrapper.h>
-#include <cds/gc/guarded_ptr.h>
#include <cds/container/details/guarded_ptr_cast.h>
namespace cds { namespace container {
/// Internal guard representation
struct guard_data {
- typedef retired_ptr_node * handoff_ptr ; ///< trapped value type
- typedef void * guarded_ptr ; ///< type of value guarded
+ typedef void * guarded_ptr; ///< type of value guarded
- atomics::atomic<guarded_ptr> pPost ; ///< pointer guarded
+ atomics::atomic<guarded_ptr> pPost; ///< pointer guarded
+ atomics::atomic<guard_data *> pGlobalNext; ///< next item of global list of allocated guards
+ atomics::atomic<guard_data *> pNextFree; ///< pointer to the next item in global or thread-local free-list
- atomics::atomic<guard_data *> pGlobalNext ; ///< next item of global list of allocated guards
- atomics::atomic<guard_data *> pNextFree ; ///< pointer to the next item in global or thread-local free-list
-
- guard_data * pThreadNext ; ///< next item of thread's local list of guards
+ guard_data * pThreadNext; ///< next item of thread's local list of guards
guard_data() CDS_NOEXCEPT
: pPost( nullptr )
details::guard_data * pGuard = m_GuardAllocator.New();
// Link guard to the list
- // m_GuardList is accumulated list and it cannot support concurrent deletion,
+ // m_GuardList is an accumulating list and it cannot support concurrent deletion,
// so, ABA problem is impossible for it
details::guard_data * pHead = m_GuardList.load( atomics::memory_order_acquire );
do {
friend class ThreadGC;
protected:
details::guard_data * m_pGuard ; ///< Pointer to guard data
+
public:
/// Initialize empty guard.
CDS_CONSTEXPR guard() CDS_NOEXCEPT
: m_pGuard( nullptr )
{}
- /// The object is not copy-constructible
+ /// Ñopy-ctor is disabled
guard( guard const& ) = delete;
+ /// Move-ctor is disabled
+ guard( guard&& ) = delete;
+
/// Object destructor, does nothing
~guard() CDS_NOEXCEPT
{}
+ /// Get current guarded pointer
+ void * get( atomics::memory_order order = atomics::memory_order_acquire ) const CDS_NOEXCEPT
+ {
+ assert( m_pGuard != nullptr );
+ return m_pGuard->pPost.load( order );
+ }
+
/// Guards pointer \p p
- void set( void * p ) CDS_NOEXCEPT
+ void set( void * p, atomics::memory_order order = atomics::memory_order_release ) CDS_NOEXCEPT
{
assert( m_pGuard != nullptr );
- m_pGuard->pPost.store( p, atomics::memory_order_release );
- //CDS_COMPILER_RW_BARRIER;
+ m_pGuard->pPost.store( p, order );
}
/// Clears the guard
- void clear() CDS_NOEXCEPT
+ void clear( atomics::memory_order order = atomics::memory_order_relaxed ) CDS_NOEXCEPT
{
assert( m_pGuard != nullptr );
- m_pGuard->pPost.store( nullptr, atomics::memory_order_relaxed );
- CDS_STRICT_DO( CDS_COMPILER_RW_BARRIER );
+ m_pGuard->pPost.store( nullptr, order );
}
/// Guards pointer \p p
GCC cannot compile code for template versions of ThreasGC::allocGuard/freeGuard,
the compiler produces error: \91cds::gc::dhp::details::guard_data* cds::gc::dhp::details::guard::m_pGuard\92 is protected
despite the fact that ThreadGC is declared as friend for guard class.
- We should not like to declare m_pGuard member as public one.
Therefore, we have to add set_guard/get_guard public functions
*/
/// Set guard data
{
return m_pGuard;
}
+
+ details::guard_data * release_guard() CDS_NOEXCEPT
+ {
+ details::guard_data * p = m_pGuard;
+ m_pGuard = nullptr;
+ return p;
+ }
+
+ bool is_initialized() const
+ {
+ return m_pGuard != nullptr;
+ }
};
} // namespace details
public:
/// Initializes guard \p g
- void allocGuard( Guard& g )
+ void allocGuard( dhp::details::guard& g )
{
assert( m_pList != nullptr );
- if ( m_pFree ) {
- g.m_pGuard = m_pFree;
- m_pFree = m_pFree->pNextFree.load(atomics::memory_order_relaxed);
- }
- else {
- g.m_pGuard = m_gc.allocGuard();
- g.m_pGuard->pThreadNext = m_pList;
- m_pList = g.m_pGuard;
+ if ( !g.m_pGuard ) {
+ if ( m_pFree ) {
+ g.m_pGuard = m_pFree;
+ m_pFree = m_pFree->pNextFree.load( atomics::memory_order_relaxed );
+ }
+ else {
+ g.m_pGuard = m_gc.allocGuard();
+ g.m_pGuard->pThreadNext = m_pList;
+ m_pList = g.m_pGuard;
+ }
}
}
/// Frees guard \p g
- void freeGuard( Guard& g )
+ void freeGuard( dhp::details::guard& g )
{
assert( m_pList != nullptr );
- g.m_pGuard->pPost.store( nullptr, atomics::memory_order_relaxed );
- g.m_pGuard->pNextFree.store( m_pFree, atomics::memory_order_relaxed );
- m_pFree = g.m_pGuard;
+ if ( g.m_pGuard ) {
+ g.m_pGuard->pPost.store( nullptr, atomics::memory_order_relaxed );
+ g.m_pGuard->pNextFree.store( m_pFree, atomics::memory_order_relaxed );
+ m_pFree = g.m_pGuard;
+ g.m_pGuard = nullptr;
+ }
}
/// Initializes guard array \p arr
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef __CDS_GC_GUARDED_PTR_H
-#define __CDS_GC_GUARDED_PTR_H
-
-#include <cds/details/defs.h>
-
-namespace cds { namespace gc {
-
- /// Guarded pointer
- /**
- A guarded pointer is a pair of the pointer and GC's guard.
- Usually, it is used for returning a pointer to the item from an lock-free container.
- The guard prevents the pointer to be early disposed (freed) by GC.
- After destructing \p %guarded_ptr object the pointer can be automatically disposed (freed) at any time.
-
- Template arguments:
- - \p GC - a garbage collector type like \p cds::gc::HP and any other from cds::gc namespace
- - \p GuardedType - a type which the guard stores
- - \p ValueType - a value type
- - \p Cast - a functor for converting <tt>GuardedType*</tt> to <tt>ValueType*</tt>. Default is \p void (no casting).
-
- For intrusive containers, \p GuardedType is the same as \p ValueType and no casting is needed.
- In such case the \p %guarded_ptr is:
- @code
- typedef cds::gc::guarded_ptr< cds::gc::HP, foo > intrusive_guarded_ptr;
- @endcode
-
- For standard (non-intrusive) containers \p GuardedType is not the same as \p ValueType and casting is needed.
- For example:
- @code
- struct foo {
- int const key;
- std::string value;
- };
-
- struct value_accessor {
- std::string* operator()( foo* pFoo ) const
- {
- return &(pFoo->value);
- }
- };
-
- // Guarded ptr
- typedef cds::gc::guarded_ptr< cds::gc::HP, Foo, std::string, value_accessor > nonintrusive_guarded_ptr;
- @endcode
-
- Many set/map container classes from \p libcds declare the typedef for \p %guarded_ptr with appropriate casting functor.
- */
- template <class GC, typename GuardedType, typename ValueType=GuardedType, typename Cast=void >
- class guarded_ptr
- {
- //TODO: use moce semantics and explicit operator bool!
- public:
- typedef GC gc; ///< Garbage collector like cds::gc::HP and any other from cds::gc namespace
- typedef GuardedType guarded_type; ///< Guarded type
- typedef ValueType value_type; ///< Value type
- typedef Cast value_cast; ///< Functor for casting \p guarded_type to \p value_type
-
- private:
- //@cond
- typename gc::Guard m_guard;
- //@endcond
-
- public:
- /// Creates empty guarded pointer
- guarded_ptr() CDS_NOEXCEPT
- {}
-
- //@cond
- /// Initializes guarded pointer with \p p
- guarded_ptr( guarded_type * p ) CDS_NOEXCEPT
- {
- m_guard.assign( p );
- }
- guarded_ptr( std::nullptr_t ) CDS_NOEXCEPT
- {}
- //@endcond
-
- /// Move ctor
- guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
- {
- m_guard.assign( gp.m_guard.get_native() );
- gp.release();
- }
-
- /// The guarded pointer is not copy-constructible
- guarded_ptr( guarded_ptr const& gp ) = delete;
-
- /// Clears the guarded pointer
- /**
- \ref release is called if guarded pointer is not \ref empty
- */
- ~guarded_ptr() CDS_NOEXCEPT
- {
- release();
- }
-
- /// Move-assignment operator
- guarded_ptr& operator=( guarded_ptr&& gp ) CDS_NOEXCEPT
- {
- m_guard.assign( gp.m_guard.get_native() );
- gp.release();
- return *this;
- }
-
- /// The guarded pointer is not copy-assignable
- guarded_ptr& operator=(guarded_ptr const& gp) = delete;
-
- /// Returns a pointer to guarded value
- value_type * operator ->() const CDS_NOEXCEPT
- {
- return value_cast()( m_guard.template get<guarded_type>() );
- }
-
- /// Returns a reference to guarded value
- value_type& operator *() CDS_NOEXCEPT
- {
- assert( !empty());
- return *value_cast()( m_guard.template get<guarded_type>() );
- }
-
- /// Returns const reference to guarded value
- value_type const& operator *() const CDS_NOEXCEPT
- {
- assert( !empty());
- return *value_cast()( m_guard.template get<guarded_type>() );
- }
-
- /// Checks if the guarded pointer is \p nullptr
- bool empty() const CDS_NOEXCEPT
- {
- return m_guard.template get<guarded_type>() == nullptr;
- }
-
- /// \p bool operator returns <tt>!empty()</tt>
- explicit operator bool() const CDS_NOEXCEPT
- {
- return !empty();
- }
-
- /// Clears guarded pointer
- /**
- If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
- Dereferncing the guarded pointer after \p release() is dangerous.
- */
- void release() CDS_NOEXCEPT
- {
- m_guard.clear();
- }
-
- //@cond
- // For internal use only!!!
- typename gc::Guard& guard() CDS_NOEXCEPT
- {
- return m_guard;
- }
- //@endcond
- };
-
-
- //@cond
- // Intrusive specialization
- template <class GC, typename T>
- class guarded_ptr< GC, T, T, void >
- {
- public:
- typedef GC gc ; ///< Garbage collector like cds::gc::HP
- typedef T guarded_type; ///< Guarded type
- typedef T value_type ; ///< Value type
-
- private:
- typename gc::Guard m_guard;
-
- public:
- guarded_ptr() CDS_NOEXCEPT
- {}
-
- guarded_ptr( value_type * p ) CDS_NOEXCEPT
- {
- m_guard.assign( p );
- }
-
- guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
- {
- m_guard.assign( gp.m_guard.get_native() );
- gp.release();
- }
-
- guarded_ptr( guarded_ptr const& gp ) = delete;
-
- ~guarded_ptr() CDS_NOEXCEPT
- {
- release();
- }
-
- guarded_ptr& operator=(guarded_ptr&& gp) CDS_NOEXCEPT
- {
- m_guard.assign( gp.m_guard.get_native() );
- gp.release();
- return *this;
- }
-
- guarded_ptr& operator=(guarded_ptr const& gp) = delete;
-
- value_type * operator ->() const CDS_NOEXCEPT
- {
- return m_guard.template get<value_type>();
- }
-
- value_type& operator *() CDS_NOEXCEPT
- {
- assert( !empty());
- return *m_guard.template get<value_type>();
- }
-
- value_type const& operator *() const CDS_NOEXCEPT
- {
- assert( !empty());
- return *m_guard.template get<value_type>();
- }
-
- bool empty() const CDS_NOEXCEPT
- {
- return m_guard.template get<guarded_type>() == nullptr;
- }
-
- explicit operator bool() const CDS_NOEXCEPT
- {
- return !empty();
- }
-
- void release() CDS_NOEXCEPT
- {
- m_guard.clear();
- }
-
- typename gc::Guard& guard() CDS_NOEXCEPT
- {
- return m_guard;
- }
- };
- //@endcond
-
-}} // namespace cds::gc
-
-#endif // #ifndef __CDS_GC_GUARDED_PTR_H
Otherwise it detaches the current thread from Dynamic Hazard Pointer GC.
*/
~thread_gc() ; // inline in dhp_impl.h
+
+ public: // for internal use only!!!
+ //@cond
+ static void alloc_guard( cds::gc::dhp::details::guard& g ); // inline in dhp_impl.h
+ static void free_guard( cds::gc::dhp::details::guard& g ); // inline in dhp_impl.h
+ //@endcond
};
typedef dhp::Guard base_class;
//@endcond
+ public: // for internal use only
+ //@cond
+ typedef cds::gc::dhp::details::guard native_guard;
+ //@endcond
+
public:
// Default ctor
Guard(); // inline in dhp_impl.h
}
};
+ /// Guarded pointer
+ /**
+ A guarded pointer is a pair of a pointer and GC's guard.
+ Usually, it is used for returning a pointer to the item from an lock-free container.
+ The guard prevents the pointer to be early disposed (freed) by GC.
+ After destructing \p %guarded_ptr object the pointer can be disposed (freed) automatically at any time.
+
+ Template arguments:
+ - \p GuardedType - a type which the guard stores
+ - \p ValueType - a value type
+ - \p Cast - a functor for converting <tt>GuardedType*</tt> to <tt>ValueType*</tt>. Default is \p void (no casting).
+
+ For intrusive containers, \p GuardedType is the same as \p ValueType and no casting is needed.
+ In such case the \p %guarded_ptr is:
+ @code
+ typedef cds::gc::DHP::guarded_ptr< foo > intrusive_guarded_ptr;
+ @endcode
+
+ For standard (non-intrusive) containers \p GuardedType is not the same as \p ValueType and casting is needed.
+ For example:
+ @code
+ struct foo {
+ int const key;
+ std::string value;
+ };
+
+ struct value_accessor {
+ std::string* operator()( foo* pFoo ) const
+ {
+ return &(pFoo->value);
+ }
+ };
+
+ // Guarded ptr
+ typedef cds::gc::DHP::guarded_ptr< Foo, std::string, value_accessor > nonintrusive_guarded_ptr;
+ @endcode
+
+ You don't need use this class directly.
+ All set/map container classes from \p libcds declare the typedef for \p %guarded_ptr with appropriate casting functor.
+ */
+ template <typename GuardedType, typename ValueType=GuardedType, typename Cast=void >
+ class guarded_ptr
+ {
+ //@cond
+ struct trivial_cast {
+ ValueType * operator()( GuardedType * p ) const
+ {
+ return p;
+ }
+ };
+ //@endcond
+
+ public:
+ typedef GuardedType guarded_type; ///< Guarded type
+ typedef ValueType value_type; ///< Value type
+
+ /// Functor for casting \p guarded_type to \p value_type
+ typedef typename std::conditional< std::is_same<Cast, void>::value, trivial_cast, Cast >::type value_cast;
+
+ //@cond
+ typedef cds::gc::dhp::details::guard native_guard;
+ //@endcond
+
+ private:
+ //@cond
+ native_guard m_guard;
+ //@endcond
+
+ public:
+ /// Creates empty guarded pointer
+ guarded_ptr() CDS_NOEXCEPT
+ {}
+
+ //@cond
+ /// Initializes guarded pointer with \p p
+ guarded_ptr( guarded_type * p ) CDS_NOEXCEPT
+ {
+ alloc_guard();
+ assert( m_guard.is_initialized() );
+ m_guard.set( p );
+ }
+ guarded_ptr( std::nullptr_t ) CDS_NOEXCEPT
+ {}
+ //@endcond
+
+ /// Move ctor
+ guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
+ {
+ m_guard.set_guard( gp.m_guard.release_guard() );
+ }
+
+ /// The guarded pointer is not copy-constructible
+ guarded_ptr( guarded_ptr const& gp ) = delete;
+
+ /// Clears the guarded pointer
+ /**
+ \ref release is called if guarded pointer is not \ref empty
+ */
+ ~guarded_ptr() CDS_NOEXCEPT
+ {
+ free_guard();
+ }
+
+ /// Move-assignment operator
+ guarded_ptr& operator=( guarded_ptr&& gp ) CDS_NOEXCEPT
+ {
+ free_guard();
+ m_guard.set_guard( gp.m_guard.release_guard() );
+ return *this;
+ }
+
+ /// The guarded pointer is not copy-assignable
+ guarded_ptr& operator=(guarded_ptr const& gp) = delete;
+
+ /// Returns a pointer to guarded value
+ value_type * operator ->() const CDS_NOEXCEPT
+ {
+ assert( !empty() );
+ return value_cast()( reinterpret_cast<guarded_type *>(m_guard.get()));
+ }
+
+ /// Returns a reference to guarded value
+ value_type& operator *() CDS_NOEXCEPT
+ {
+ assert( !empty());
+ return *value_cast()(reinterpret_cast<guarded_type *>(m_guard.get()));
+ }
+
+ /// Returns const reference to guarded value
+ value_type const& operator *() const CDS_NOEXCEPT
+ {
+ assert( !empty() );
+ return *value_cast()(reinterpret_cast<guarded_type *>(m_guard.get()));
+ }
+
+ /// Checks if the guarded pointer is \p nullptr
+ bool empty() const CDS_NOEXCEPT
+ {
+ return !m_guard.is_initialized() || m_guard.get() == nullptr;
+ }
+
+ /// \p bool operator returns <tt>!empty()</tt>
+ explicit operator bool() const CDS_NOEXCEPT
+ {
+ return !empty();
+ }
+
+ /// Clears guarded pointer
+ /**
+ If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
+ Dereferncing the guarded pointer after \p release() is dangerous.
+ */
+ void release() CDS_NOEXCEPT
+ {
+ if ( m_guard.is_initialized() )
+ m_guard.clear();
+ }
+
+ //@cond
+ // For internal use only!!!
+ native_guard& guard() CDS_NOEXCEPT
+ {
+ alloc_guard();
+ assert( m_guard.is_initialized() );
+ return m_guard;
+ }
+ //@endcond
+
+ private:
+ //@cond
+ void alloc_guard()
+ {
+ if ( !m_guard.is_initialized() )
+ thread_gc::alloc_guard( m_guard );
+ }
+
+ void free_guard()
+ {
+ if ( m_guard.is_initialized() )
+ thread_gc::free_guard( m_guard );
+ }
+ //@endcond
+ };
+
public:
/// Initializes dhp::GarbageCollector singleton
/**
cds::threading::Manager::detachThread();
}
+ inline /*static*/ void DHP::thread_gc::alloc_guard( cds::gc::dhp::details::guard& g )
+ {
+ return cds::threading::getGC<DHP>().allocGuard(g);
+ }
+ inline /*static*/ void DHP::thread_gc::free_guard( cds::gc::dhp::details::guard& g )
+ {
+ cds::threading::getGC<DHP>().freeGuard(g);
+ }
+
inline DHP::Guard::Guard()
: Guard::base_class( cds::threading::getGC<DHP>() )
{}
Otherwise it detaches the current thread from Hazard Pointer GC.
*/
~thread_gc() ; // inline in hp_impl.h
+
+ public: // for internal use only!!!
+ //@cond
+ static cds::gc::hp::details::hp_guard& alloc_guard(); // inline in hp_impl.h
+ static void free_guard( cds::gc::hp::details::hp_guard& g ); // inline in hp_impl.h
+ //@endcond
};
/// Hazard Pointer guard
}
};
+ /// Guarded pointer
+ /**
+ A guarded pointer is a pair of a pointer and GC's guard.
+ Usually, it is used for returning a pointer to the item from an lock-free container.
+ The guard prevents the pointer to be early disposed (freed) by GC.
+ After destructing \p %guarded_ptr object the pointer can be disposed (freed) automatically at any time.
+
+ Template arguments:
+ - \p GuardedType - a type which the guard stores
+ - \p ValueType - a value type
+ - \p Cast - a functor for converting <tt>GuardedType*</tt> to <tt>ValueType*</tt>. Default is \p void (no casting).
+
+ For intrusive containers, \p GuardedType is the same as \p ValueType and no casting is needed.
+ In such case the \p %guarded_ptr is:
+ @code
+ typedef cds::gc::HP::guarded_ptr< foo > intrusive_guarded_ptr;
+ @endcode
+
+ For standard (non-intrusive) containers \p GuardedType is not the same as \p ValueType and casting is needed.
+ For example:
+ @code
+ struct foo {
+ int const key;
+ std::string value;
+ };
+
+ struct value_accessor {
+ std::string* operator()( foo* pFoo ) const
+ {
+ return &(pFoo->value);
+ }
+ };
+
+ // Guarded ptr
+ typedef cds::gc::HP::guarded_ptr< Foo, std::string, value_accessor > nonintrusive_guarded_ptr;
+ @endcode
+
+ You don't need use this class directly.
+ All set/map container classes from \p libcds declare the typedef for \p %guarded_ptr with appropriate casting functor.
+ */
+ template <typename GuardedType, typename ValueType=GuardedType, typename Cast=void >
+ class guarded_ptr
+ {
+ //@cond
+ struct trivial_cast {
+ ValueType * operator()( GuardedType * p ) const
+ {
+ return p;
+ }
+ };
+ //@endcond
+
+ public:
+ typedef GuardedType guarded_type; ///< Guarded type
+ typedef ValueType value_type; ///< Value type
+
+ /// Functor for casting \p guarded_type to \p value_type
+ typedef typename std::conditional< std::is_same<Cast, void>::value, trivial_cast, Cast >::type value_cast;
+
+ //@cond
+ typedef cds::gc::hp::details::hp_guard native_guard;
+ //@endcond
+
+ private:
+ //@cond
+ native_guard * m_pGuard;
+ //@endcond
+
+ public:
+ /// Creates empty guarded pointer
+ guarded_ptr() CDS_NOEXCEPT
+ : m_pGuard(nullptr)
+ {}
+
+ //@cond
+ /// Initializes guarded pointer with \p p
+ guarded_ptr( guarded_type * p ) CDS_NOEXCEPT
+ {
+ alloc_guard();
+ assert( m_pGuard );
+ m_pGuard->set(p);
+ }
+ guarded_ptr( std::nullptr_t ) CDS_NOEXCEPT
+ : m_pGuard( nullptr )
+ {}
+ //@endcond
+
+ /// Move ctor
+ guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
+ : m_pGuard( gp.m_pGuard )
+ {
+ gp.m_pGuard = nullptr;
+ }
+
+ /// The guarded pointer is not copy-constructible
+ guarded_ptr( guarded_ptr const& gp ) = delete;
+
+ /// Clears the guarded pointer
+ /**
+ \ref release is called if guarded pointer is not \ref empty
+ */
+ ~guarded_ptr() CDS_NOEXCEPT
+ {
+ free_guard();
+ }
+
+ /// Move-assignment operator
+ guarded_ptr& operator=( guarded_ptr&& gp ) CDS_NOEXCEPT
+ {
+ free_guard();
+ m_pGuard = gp.m_pGuard;
+ gp.m_pGuard = nullptr;
+ return *this;
+ }
+
+ /// The guarded pointer is not copy-assignable
+ guarded_ptr& operator=(guarded_ptr const& gp) = delete;
+
+ /// Returns a pointer to guarded value
+ value_type * operator ->() const CDS_NOEXCEPT
+ {
+ assert( !empty() );
+ return value_cast()( reinterpret_cast<guarded_type *>(m_pGuard->get()));
+ }
+
+ /// Returns a reference to guarded value
+ value_type& operator *() CDS_NOEXCEPT
+ {
+ assert( !empty());
+ return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
+ }
+
+ /// Returns const reference to guarded value
+ value_type const& operator *() const CDS_NOEXCEPT
+ {
+ assert( !empty() );
+ return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
+ }
+
+ /// Checks if the guarded pointer is \p nullptr
+ bool empty() const CDS_NOEXCEPT
+ {
+ return !m_pGuard || m_pGuard->get() == nullptr;
+ }
+
+ /// \p bool operator returns <tt>!empty()</tt>
+ explicit operator bool() const CDS_NOEXCEPT
+ {
+ return !empty();
+ }
+
+ /// Clears guarded pointer
+ /**
+ If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
+ Dereferncing the guarded pointer after \p release() is dangerous.
+ */
+ void release() CDS_NOEXCEPT
+ {
+ if ( m_pGuard )
+ m_pGuard->clear();
+ }
+
+ //@cond
+ // For internal use only!!!
+ native_guard& guard() CDS_NOEXCEPT
+ {
+ alloc_guard();
+ assert( m_pGuard );
+ return *m_pGuard;
+ }
+ //@endcond
+
+ private:
+ //@cond
+ void alloc_guard()
+ {
+ if ( !m_pGuard )
+ m_pGuard = &thread_gc::alloc_guard();
+ }
+
+ void free_guard()
+ {
+ if ( m_pGuard ) {
+ thread_gc::free_guard( *m_pGuard );
+ m_pGuard = nullptr;
+ }
+ }
+ //@endcond
+ };
+
public:
/// \p scan() type
enum class scan_type {
cds::threading::Manager::detachThread();
}
+ inline /*static*/ cds::gc::hp::details::hp_guard& HP::thread_gc::alloc_guard()
+ {
+ return cds::threading::getGC<HP>().allocGuard();
+ }
+
+ inline /*static*/ void HP::thread_gc::free_guard( cds::gc::hp::details::hp_guard& g )
+ {
+ cds::threading::getGC<HP>().freeGuard( g );
+ }
+
inline HP::Guard::Guard()
: Guard::base_class( cds::threading::getGC<HP>() )
{}
#include <cds/opt/compare.h>
#include <cds/details/binary_functor_wrapper.h>
#include <cds/urcu/details/check_deadlock.h>
-#include <cds/gc/guarded_ptr.h>
namespace cds { namespace intrusive {
typedef typename traits::disposer disposer; ///< leaf node disposer
typedef typename traits::back_off back_off; ///< back-off strategy
- typedef cds::gc::guarded_ptr< gc, value_type > guarded_ptr; ///< Guarded pointer
+ typedef typename gc::template guarded_ptr< value_type > guarded_ptr; ///< Guarded pointer
protected:
//@cond
}
template <typename Q>
- bool extract_( typename gc::Guard& guard, Q const& key )
+ bool extract_( typename guarded_ptr::native_guard& guard, Q const& key )
{
- guarded_ptr gp;
return erase_( key, node_compare(),
[]( Q const&, leaf_node const& ) -> bool { return true; },
- [&guard]( value_type& found ) { guard.assign( &found ); } );
+ [&guard]( value_type& found ) { guard.set( &found ); } );
}
template <typename Q, typename Less>
- bool extract_with_( typename gc::Guard& guard, Q const& key, Less pred )
+ bool extract_with_( typename guarded_ptr::native_guard& guard, Q const& key, Less pred )
{
typedef ellen_bintree::details::compare<
key_type,
return erase_( key, compare_functor(),
[]( Q const&, leaf_node const& ) -> bool { return true; },
- [&guard]( value_type& found ) { guard.assign( &found ); } );
+ [&guard]( value_type& found ) { guard.set( &found ); } );
}
- bool extract_max_( typename gc::Guard& gp )
+ bool extract_max_( typename guarded_ptr::native_guard& gp )
{
update_desc * pOp = nullptr;
search_result res;
--m_ItemCounter;
m_Stat.onExtractMaxSuccess();
- gp.assign( node_traits::to_value_ptr( res.pLeaf ));
+ gp.set( node_traits::to_value_ptr( res.pLeaf ));
return true;
}
- bool extract_min_( typename gc::Guard& gp )
+ bool extract_min_( typename guarded_ptr::native_guard& gp )
{
update_desc * pOp = nullptr;
search_result res;
--m_ItemCounter;
m_Stat.onExtractMinSuccess();
- gp.assign( node_traits::to_value_ptr( res.pLeaf ));
+ gp.set( node_traits::to_value_ptr( res.pLeaf ));
return true;
}
}
template <typename Q>
- bool get_( typename gc::Guard& guard, Q const& val ) const
+ bool get_( typename guarded_ptr::native_guard& guard, Q const& val ) const
{
- return find_( val, [&guard]( value_type& found, Q const& ) { guard.assign( &found ); } );
+ return find_( val, [&guard]( value_type& found, Q const& ) { guard.set( &found ); } );
}
template <typename Q, typename Less>
- bool get_with_( typename gc::Guard& guard, Q const& val, Less pred ) const
+ bool get_with_( typename guarded_ptr::native_guard& guard, Q const& val, Less pred ) const
{
- return find_with_( val, pred, [&guard]( value_type& found, Q const& ) { guard.assign( &found ); } );
+ return find_with_( val, pred, [&guard]( value_type& found, Q const& ) { guard.set( &found ); } );
}
//@endcond
#include <mutex> // unique_lock
#include <cds/intrusive/details/lazy_list_base.h>
-#include <cds/gc/guarded_ptr.h>
namespace cds { namespace intrusive {
#define __CDS_INTRUSIVE_IMPL_MICHAEL_LIST_H
#include <cds/intrusive/details/michael_list_base.h>
-#include <cds/gc/guarded_ptr.h>
#include <cds/details/make_const_type.h>
namespace cds { namespace intrusive {
#include <cds/intrusive/details/skip_list_base.h>
#include <cds/opt/compare.h>
#include <cds/details/binary_functor_wrapper.h>
-#include <cds/gc/guarded_ptr.h>
namespace cds { namespace intrusive {
<ClInclude Include="..\..\..\cds\gc\details\hp_alloc.h" />\r
<ClInclude Include="..\..\..\cds\gc\details\hp_type.h" />\r
<ClInclude Include="..\..\..\cds\gc\dhp.h" />\r
- <ClInclude Include="..\..\..\cds\gc\guarded_ptr.h" />\r
<ClInclude Include="..\..\..\cds\gc\impl\dhp_decl.h" />\r
<ClInclude Include="..\..\..\cds\gc\impl\dhp_impl.h" />\r
<ClInclude Include="..\..\..\cds\gc\impl\hp_decl.h" />\r
<ClInclude Include="..\..\..\cds\details\defs.h">\r
<Filter>Header Files\cds\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\gc\guarded_ptr.h">\r
- <Filter>Header Files\cds\gc</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\cds\details\is_aligned.h">\r
<Filter>Header Files\cds\details</Filter>\r
</ClInclude>\r