3 #ifndef CDSLIB_CONTAINER_SKIP_LIST_SET_NOGC_H
4 #define CDSLIB_CONTAINER_SKIP_LIST_SET_NOGC_H
6 #include <cds/intrusive/skip_list_nogc.h>
7 #include <cds/container/details/skip_list_base.h>
8 #include <cds/details/binary_functor_wrapper.h>
9 #include <cds/gc/nogc.h>
10 #include <cds/details/allocator.h>
12 namespace cds { namespace container {
14 namespace skip_list { namespace details {
15 struct set_key_accessor
17 template <typename NodeType>
18 typename NodeType::stored_value_type const& operator()( NodeType const& node ) const
23 }} // namespace skip_list::details
26 template <typename T, typename Traits >
27 struct make_skip_list_set_nogc
29 typedef cds::gc::nogc gc;
31 typedef Traits traits;
33 typedef cds::intrusive::skip_list::node< gc > intrusive_node_type;
34 struct node_type: public intrusive_node_type
36 typedef intrusive_node_type base_class;
37 typedef typename base_class::atomic_ptr atomic_ptr;
38 typedef atomic_ptr tower_item_type;
39 typedef value_type stored_value_type;
42 //atomic_ptr m_arrTower[] ; // allocated together with node_type in single memory block
45 node_type( unsigned int nHeight, atomic_ptr * pTower, Q const& v )
49 new (pTower) atomic_ptr[ nHeight - 1 ];
50 base_class::make_tower( nHeight, pTower );
54 template <typename Q, typename... Args>
55 node_type( unsigned int nHeight, atomic_ptr * pTower, Q&& q, Args&&... args )
56 : m_Value( std::forward<Q>(q), std::forward<Args>(args)... )
59 new (pTower) atomic_ptr[ nHeight - 1 ];
60 base_class::make_tower( nHeight, pTower );
64 node_type() = delete; // no default ctor
67 typedef skip_list::details::node_allocator< node_type, traits> node_allocator;
69 struct node_deallocator {
70 void operator ()( node_type * pNode )
72 node_allocator().Delete( pNode );
76 typedef skip_list::details::dummy_node_builder<intrusive_node_type> dummy_node_builder;
78 typedef typename traits::key_accessor key_accessor;
79 typedef typename opt::details::make_comparator< value_type, traits >::type key_comparator;
82 template <typename Less>
84 typedef compare_wrapper< node_type, cds::opt::details::make_comparator_from_less<Less>, key_accessor > type;
88 typedef typename cds::intrusive::skip_list::make_traits<
89 cds::opt::type_traits< traits >
90 ,cds::intrusive::opt::hook< intrusive::skip_list::base_hook< cds::opt::gc< gc > > >
91 ,cds::intrusive::opt::disposer< node_deallocator >
92 ,cds::intrusive::skip_list::internal_node_builder< dummy_node_builder >
93 ,cds::opt::compare< cds::details::compare_wrapper< node_type, key_comparator, key_accessor > >
94 >::type intrusive_type_traits;
96 typedef cds::intrusive::SkipListSet< gc, node_type, intrusive_type_traits> type;
98 } // namespace details
101 /// Lock-free skip-list set (template specialization for gc::nogc)
102 /** @ingroup cds_nonintrusive_set
103 \anchor cds_nonintrusive_SkipListSet_nogc
105 This specialization is intended for so-called persistent usage when no item
106 reclamation may be performed. The class does not support deleting of list item.
107 See \ref cds_nonintrusive_SkipListSet_hp "SkipListSet" for detailed description.
110 - \p T - type to be stored in the list.
111 - \p Traits - type traits. See skip_list::traits for explanation.
113 It is possible to declare option-based list with cds::container::skip_list::make_traits metafunction istead of \p Traits template
114 argument. \p Options template arguments of cds::container::skip_list::make_traits metafunction are:
115 - opt::compare - key comparison functor. No default functor is provided.
116 If the option is not specified, the opt::less is used.
117 - opt::less - specifies binary predicate used for key comparison. Default is \p std::less<T>.
118 - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter that is no item counting.
119 - opt::memory_model - C++ memory ordering model. Can be opt::v::relaxed_ordering (relaxed memory model, the default)
120 or opt::v::sequential_consistent (sequentially consisnent memory model).
121 - skip_list::random_level_generator - random level generator. Can be skip_list::xorshift, skip_list::turbo_pascal or
122 user-provided one. See skip_list::random_level_generator option description for explanation.
123 Default is \p %skip_list::turbo_pascal.
124 - opt::allocator - allocator for skip-list node. Default is \ref CDS_DEFAULT_ALLOCATOR.
125 - opt::back_off - back-off strategy used. If the option is not specified, the cds::backoff::Default is used.
126 - opt::stat - internal statistics. Available types: skip_list::stat, skip_list::empty_stat (the default)
130 #ifdef CDS_DOXYGEN_INVOKED
131 class Traits = skip_list::traits
136 class SkipListSet< gc::nogc, T, Traits >:
137 #ifdef CDS_DOXYGEN_INVOKED
138 protected intrusive::SkipListSet< cds::gc::nogc, T, Traits >
140 protected details::make_skip_list_set_nogc< T, typename cds::opt::replace_key_accessor< Traits, skip_list::details::set_key_accessor >::type >::type
144 typedef details::make_skip_list_set_nogc< T, typename cds::opt::replace_key_accessor< Traits, skip_list::details::set_key_accessor >::type > maker;
145 typedef typename maker::type base_class;
148 typedef typename base_class::gc gc ; ///< Garbage collector used
149 typedef T value_type ; ///< Value type stored in the set
150 typedef Traits options ; ///< Options specified
152 typedef typename base_class::back_off back_off ; ///< Back-off strategy used
153 typedef typename options::allocator allocator_type ; ///< Allocator type used for allocate/deallocate the skip-list nodes
154 typedef typename base_class::item_counter item_counter ; ///< Item counting policy used
155 typedef typename maker::key_comparator key_comparator ; ///< key compare functor
156 typedef typename base_class::memory_model memory_model ; ///< Memory ordering. See cds::opt::memory_model option
157 typedef typename options::stat stat ; ///< internal statistics type
158 typedef typename base_class::random_level_generator random_level_generator ; ///< random level generator
161 typedef cds::container::skip_list::implementation_tag implementation_tag;
166 typedef typename maker::node_type node_type;
167 typedef typename maker::node_allocator node_allocator;
168 typedef typename std::conditional<
169 std::is_same< typename options::key_accessor, opt::none >::value,
170 skip_list::details::set_key_accessor,
171 typename options::key_accessor
172 >::type key_accessor;
174 typedef std::unique_ptr< node_type, typename maker::node_deallocator > scoped_node_ptr;
179 typedef skip_list::details::iterator< typename base_class::iterator > iterator;
181 /// Const iterator type
182 typedef skip_list::details::iterator< typename base_class::const_iterator > const_iterator;
184 /// Returns a forward iterator addressing the first element in a set
187 return iterator( base_class::begin() );
190 /// Returns a forward const iterator addressing the first element in a set
192 const_iterator begin() const
194 return const_iterator( base_class::begin() );
196 const_iterator cbegin() const
198 return const_iterator( base_class::cbegin() );
202 /// Returns a forward iterator that addresses the location succeeding the last element in a set.
205 return iterator( base_class::end() );
208 /// Returns a forward const iterator that addresses the location succeeding the last element in a set.
210 const_iterator end() const
212 return const_iterator( base_class::end() );
214 const_iterator cend() const
216 return const_iterator( base_class::cend() );
222 static iterator node_to_iterator( node_type * pNode )
225 return iterator( base_class::iterator::from_node( pNode ));
235 /// Destructor destroys the set object
241 The function inserts \p val in the set if it does not contain
242 an item with key equal to \p val.
244 Return an iterator pointing to inserted item if success, otherwise \ref end()
246 template <typename Q>
247 iterator insert( const Q& val )
249 scoped_node_ptr sp( node_allocator().New( base_class::random_level(), val ));
250 if ( base_class::insert( *sp.get() )) {
251 return node_to_iterator( sp.release() );
256 /// Inserts data of type \ref value_type constructed with <tt>std::forward<Args>(args)...</tt>
258 Return an iterator pointing to inserted item if success \ref end() otherwise
260 template <typename... Args>
261 iterator emplace( Args&&... args )
263 scoped_node_ptr sp( node_allocator().New( base_class::random_level(), std::forward<Args>(args)... ));
264 if ( base_class::insert( *sp.get() )) {
265 return node_to_iterator( sp.release() );
272 The operation inserts new item if \p val is not found in the set and \p bInsert is \p true.
273 Otherwise, if that key exists, the function returns an iterator that points to item found.
275 Returns <tt> std::pair<iterator, bool> </tt> where \p first is an iterator pointing to
276 item found or inserted or \p end() if \p val is not found and \p bInsert is \p false,
277 \p second is \p true if new item has been added or \p false if the item
278 already is in the set.
280 template <typename Q>
281 std::pair<iterator, bool> update( const Q& val, bool bInsert = true )
283 scoped_node_ptr sp( node_allocator().New( base_class::random_level(), val ));
285 std::pair<bool, bool> bRes = base_class::update( *sp, [&pNode](bool, node_type& item, node_type&) { pNode = &item; }, bInsert );
286 if ( bRes.first && bRes.second )
288 else if ( !bRes.first )
289 return std::make_pair( end(), false );
291 return std::make_pair( node_to_iterator( pNode ), bRes.second );
294 // Deprecated, use update()
295 template <typename Q>
296 std::pair<iterator, bool> ensure( const Q& val )
298 return update( val, true );
302 /// Checks whether the set contains \p key
304 The function searches the item with key equal to \p key
305 and returns an iterator to item found or \p end() if the key is not fund
307 template <typename Q>
308 iterator contains( Q const& key ) const
310 node_type * pNode = base_class::contains( key );
312 return node_to_iterator( pNode );
313 return base_class::nonconst_end();
316 // Deprecated, use contains()
317 template <typename Q>
318 iterator find( Q const& key ) const
320 return contains( key );
324 /// Checks whether the set contains \p key using \p pred predicate for searching
326 The function is similar to <tt>contains( key )</tt> but \p pred is used for key comparing.
327 \p Less functor has the interface like \p std::less.
328 \p Less must imply the same element order as the comparator used for building the set.
330 template <typename Q, typename Less>
331 iterator contains( Q const& key, Less pred ) const
334 node_type * pNode = base_class::contains( key, cds::details::predicate_wrapper< node_type, Less, key_accessor>() );
336 return node_to_iterator( pNode );
337 return base_class::nonconst_end();
340 // Deprecated, use contains()
341 template <typename Q, typename Less>
342 iterator find_with( Q const& key, Less pred ) const
344 return contains( key, pred );
348 /// Gets minimum key from the set
350 If the set is empty the function returns \p nullptr
352 value_type * get_min() const
354 node_type * pNode = base_class::get_min();
355 return pNode ? &pNode->m_Value : nullptr;
358 /// Gets maximum key from the set
360 The function returns \p nullptr if the set is empty
362 value_type * get_max() const
364 node_type * pNode = base_class::get_max();
365 return pNode ? &pNode->m_Value : nullptr;
368 /// Clears the set (non-atomic)
370 The function is not atomic.
371 Finding and/or inserting is prohibited while clearing.
372 Otherwise an unpredictable result may be encountered.
373 Thus, \p clear() may be used only for debugging purposes.
380 /// Checks if the set is empty
383 return base_class::empty();
386 /// Returns item count in the set
388 The value returned depends on item counter type provided by \p Traits template parameter.
389 If it is atomicity::empty_item_counter this function always returns 0.
390 The function is not suitable for checking the set emptiness, use \ref empty
391 member function for this purpose.
395 return base_class::size();
398 /// Returns maximum height of skip-list. The max height is a constant for each object and does not exceed 32.
399 static CDS_CONSTEXPR unsigned int max_height() CDS_NOEXCEPT
401 return base_class::max_height();
404 /// Returns const reference to internal statistics
405 stat const& statistics() const
407 return base_class::statistics();
413 #endif // ifndef CDSLIB_CONTAINER_SKIP_LIST_SET_NOGC_H