Removed redundant spaces
[libcds.git] / cds / container / michael_kvlist_nogc.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
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.
18
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.
29 */
30
31 #ifndef CDSLIB_CONTAINER_MICHAEL_KVLIST_NOGC_H
32 #define CDSLIB_CONTAINER_MICHAEL_KVLIST_NOGC_H
33
34 #include <memory>
35 #include <cds/container/details/michael_list_base.h>
36 #include <cds/intrusive/michael_list_nogc.h>
37 #include <cds/container/details/make_michael_kvlist.h>
38
39 namespace cds { namespace container {
40
41     //@cond
42     namespace details {
43
44         template <typename K, typename T, class Traits>
45         struct make_michael_kvlist_nogc: public make_michael_kvlist<gc::nogc, K, T, Traits>
46         {
47             typedef make_michael_kvlist<cds::gc::nogc, K, T, Traits>  base_maker;
48             typedef typename base_maker::node_type node_type;
49
50             struct intrusive_traits: public base_maker::intrusive_traits
51             {
52                 typedef typename base_maker::node_deallocator    disposer;
53             };
54
55             typedef intrusive::MichaelList<cds::gc::nogc, node_type, intrusive_traits>  type;
56         };
57
58     }   // namespace details
59     //@endcond
60
61     /// Michael's ordered list (key-value pair, template specialization for gc::nogc)
62     /** @ingroup cds_nonintrusive_list
63         @anchor cds_nonintrusive_MichaelKVList_nogc
64
65         This specialization is intended for so-called persistent usage when no item
66         reclamation may be performed. The class does not support deleting of list item.
67
68         Usually, ordered single-linked list is used as a building block for the hash table implementation.
69         The complexity of searching is <tt>O(N)</tt>.
70
71         See \ref cds_nonintrusive_MichaelList_gc "MichaelList" for description of template parameters.
72
73         The interface of the specialization is a little different.
74     */
75     template <
76         typename Key,
77         typename Value,
78 #ifdef CDS_DOXYGEN_INVOKED
79         typename Traits = michael_list::traits
80 #else
81         typename Traits
82 #endif
83     >
84     class MichaelKVList<gc::nogc, Key, Value, Traits>:
85 #ifdef CDS_DOXYGEN_INVOKED
86         protected intrusive::MichaelList< gc::nogc, implementation_defined, Traits >
87 #else
88         protected details::make_michael_kvlist_nogc< Key, Value, Traits >::type
89 #endif
90     {
91         //@cond
92         typedef details::make_michael_kvlist_nogc< Key, Value, Traits > maker;
93         typedef typename maker::type  base_class;
94         //@endcond
95
96     public:
97         typedef cds::gc::nogc gc;         ///< Garbage collector used
98         typedef Traits        traits;     ///< List traits
99
100 #ifdef CDS_DOXYGEN_INVOKED
101         typedef Key                                 key_type        ;   ///< Key type
102         typedef Value                               mapped_type     ;   ///< Type of value stored in the list
103         typedef std::pair<key_type const, mapped_type> value_type   ;   ///< key/value pair stored in the list
104 #else
105         typedef typename maker::key_type          key_type;
106         typedef typename maker::value_type        mapped_type;
107         typedef typename maker::pair_type         value_type;
108 #endif
109
110         typedef typename base_class::back_off     back_off;       ///< Back-off strategy used
111         typedef typename maker::allocator_type    allocator_type; ///< Allocator type used for allocate/deallocate the nodes
112         typedef typename base_class::item_counter item_counter;   ///< Item counting policy used
113         typedef typename maker::key_comparator    key_comparator; ///< key comparison functor
114         typedef typename base_class::memory_model memory_model;   ///< Memory ordering. See cds::opt::memory_model option
115         typedef typename base_class::stat         stat;           ///< Internal statistics
116
117         //@cond
118         // Rebind traits (split-list support)
119         template <typename... Options>
120         struct rebind_traits {
121             typedef MichaelKVList<
122                 gc
123                 , key_type, mapped_type
124                 , typename cds::opt::make_options< traits, Options...>::type
125             > type;
126         };
127
128         // Stat selector
129         template <typename Stat>
130         using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >;
131         //@endcond
132
133     protected:
134         //@cond
135         typedef typename base_class::value_type   node_type;
136         typedef typename maker::cxx_allocator     cxx_allocator;
137         typedef typename maker::node_deallocator  node_deallocator;
138         typedef typename maker::intrusive_traits::compare  intrusive_key_comparator;
139
140         typedef typename base_class::atomic_node_ptr head_type;
141
142         struct node_disposer {
143             void operator()( node_type * pNode )
144             {
145                 free_node( pNode );
146             }
147         };
148         typedef std::unique_ptr< node_type, node_disposer >     scoped_node_ptr;
149         //@endcond
150
151     protected:
152         //@cond
153         template <bool IsConst>
154         class iterator_type: protected base_class::template iterator_type<IsConst>
155         {
156             typedef typename base_class::template iterator_type<IsConst>    iterator_base;
157
158             iterator_type( head_type const& refNode )
159                 : iterator_base( refNode )
160             {}
161
162             explicit iterator_type( const iterator_base& it )
163                 : iterator_base( it )
164             {}
165
166             friend class MichaelKVList;
167
168         protected:
169             explicit iterator_type( node_type& pNode )
170                 : iterator_base( &pNode )
171             {}
172
173         public:
174             typedef typename cds::details::make_const_type<mapped_type, IsConst>::reference  value_ref;
175             typedef typename cds::details::make_const_type<mapped_type, IsConst>::pointer    value_ptr;
176
177             typedef typename cds::details::make_const_type<value_type,  IsConst>::reference  pair_ref;
178             typedef typename cds::details::make_const_type<value_type,  IsConst>::pointer    pair_ptr;
179
180             iterator_type()
181                 : iterator_base()
182             {}
183
184             iterator_type( const iterator_type& src )
185                 : iterator_base( src )
186             {}
187
188             key_type const& key() const
189             {
190                 typename iterator_base::value_ptr p = iterator_base::operator ->();
191                 assert( p != nullptr );
192                 return p->m_Data.first;
193             }
194
195             value_ref val() const
196             {
197                 typename iterator_base::value_ptr p = iterator_base::operator ->();
198                 assert( p != nullptr );
199                 return p->m_Data.second;
200             }
201
202             pair_ptr operator ->() const
203             {
204                 typename iterator_base::value_ptr p = iterator_base::operator ->();
205                 return p ? &(p->m_Data) : nullptr;
206             }
207
208             pair_ref operator *() const
209             {
210                 typename iterator_base::value_ref p = iterator_base::operator *();
211                 return p.m_Data;
212             }
213
214             /// Pre-increment
215             iterator_type& operator ++()
216             {
217                 iterator_base::operator ++();
218                 return *this;
219             }
220
221             /// Post-increment
222             iterator_type operator ++(int)
223             {
224                 return iterator_base::operator ++(0);
225             }
226
227             template <bool C>
228             bool operator ==(iterator_type<C> const& i ) const
229             {
230                 return iterator_base::operator ==(i);
231             }
232             template <bool C>
233             bool operator !=(iterator_type<C> const& i ) const
234             {
235                 return iterator_base::operator !=(i);
236             }
237         };
238         //@endcond
239
240     public:
241     ///@name Forward iterators
242     //@{
243         /// Forward iterator
244         /**
245             The forward iterator is safe: you may use it in multi-threaded enviromnent without any synchronization.
246
247             The forward iterator for Michael's list based on \p gc::nogc has pre- and post-increment operators.
248
249             The iterator interface to access item data:
250             - <tt> operator -> </tt> - returns a pointer to \p value_type
251             - <tt> operator *</tt> - returns a reference (a const reference for \p const_iterator) to \p value_type
252             - <tt> const key_type& key() </tt> - returns a key reference for iterator
253             - <tt> mapped_type& val() </tt> - retuns a value reference for iterator (const reference for \p const_iterator)
254
255             For both functions the iterator should not be equal to \p end().
256
257             @note \p end() iterator is not dereferenceable
258         */
259         typedef iterator_type<false>    iterator;
260
261         /// Const forward iterator
262         /**
263             For iterator's features and requirements see \ref iterator
264         */
265         typedef iterator_type<true>     const_iterator;
266
267         /// Returns a forward iterator addressing the first element in a list
268         /**
269             For empty list \code begin() == end() \endcode
270         */
271         iterator begin()
272         {
273             return iterator( head());
274         }
275
276         /// Returns an iterator that addresses the location succeeding the last element in a list
277         /**
278             Do not use the value returned by <tt>end</tt> function to access any item.
279             Internally, <tt>end</tt> returning value equals to \p nullptr.
280
281             The returned value can be used only to control reaching the end of the list.
282             For empty list \code begin() == end() \endcode
283         */
284         iterator end()
285         {
286             return iterator();
287         }
288
289         /// Returns a forward const iterator addressing the first element in a list
290         const_iterator begin() const
291         {
292             return const_iterator( head());
293         }
294         /// Returns a forward const iterator addressing the first element in a list
295         const_iterator cbegin() const
296         {
297             return const_iterator( head());
298         }
299
300         /// Returns an const iterator that addresses the location succeeding the last element in a list
301         const_iterator end() const
302         {
303             return const_iterator();
304         }
305         /// Returns an const iterator that addresses the location succeeding the last element in a list
306         const_iterator cend() const
307         {
308             return const_iterator();
309         }
310     //@}
311
312     public:
313         /// Default constructor
314         /**
315             Initialize empty list
316         */
317         MichaelKVList()
318         {}
319
320         //@cond
321         template <typename Stat, typename = std::enable_if<std::is_same<stat, michael_list::wrapped_stat<Stat>>::value >>
322         explicit MichaelKVList( Stat& st )
323             : base_class( st )
324         {}
325         //@endcond
326
327         /// List destructor
328         /**
329             Clears the list
330         */
331         ~MichaelKVList()
332         {
333             clear();
334         }
335
336         /// Inserts new node with key and default value
337         /**
338             The function creates a node with \p key and default value, and then inserts the node created into the list.
339
340             Preconditions:
341             - The \ref key_type should be constructible from value of type \p K.
342                 In trivial case, \p K is equal to \ref key_type.
343             - The \ref mapped_type should be default-constructible.
344
345             Returns an iterator pointed to inserted value, or \p end() if inserting is failed
346         */
347         template <typename K>
348         iterator insert( const K& key )
349         {
350             return node_to_iterator( insert_at( head(), key ));
351         }
352
353         /// Inserts new node with a key and a value
354         /**
355             The function creates a node with \p key and value \p val, and then inserts the node created into the list.
356
357             Preconditions:
358             - The \ref key_type should be constructible from \p key of type \p K.
359             - The \ref mapped_type should be constructible from \p val of type \p V.
360
361             Returns an iterator pointed to inserted value, or \p end() if inserting is failed
362         */
363         template <typename K, typename V>
364         iterator insert( const K& key, const V& val )
365         {
366             // We cannot use insert with functor here
367             // because we cannot lock inserted node for updating
368             // Therefore, we use separate function
369             return node_to_iterator( insert_at( head(), key, val ));
370         }
371
372         /// Inserts new node and initialize it by a functor
373         /**
374             This function inserts new node with key \p key and if inserting is successful then it calls
375             \p func functor with signature
376             \code void func( value_type& item );
377                 struct functor {
378                     void operator()( value_type& item );
379                 };
380             \endcode
381
382             The argument \p item of user-defined functor \p func is the reference
383             to the list's item inserted. <tt>item.second</tt> is a reference to item's value that may be changed.
384             User-defined functor \p func should guarantee that during changing item's value no any other changes
385             could be made on this list's item by concurrent threads.
386
387             The key_type should be constructible from value of type \p K.
388
389             The function allows to split creating of new item into two part:
390             - create item from \p key;
391             - insert new item into the list;
392             - if inserting is successful, initialize the value of item by calling \p f functor
393
394             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
395             it is preferable that the initialization should be completed only if inserting is successful.
396
397             Returns an iterator pointed to inserted value, or \p end() if inserting is failed
398         */
399         template <typename K, typename Func>
400         iterator insert_with( const K& key, Func func )
401         {
402             return node_to_iterator( insert_with_at( head(), key, func ));
403         }
404
405         /// Updates the item
406         /**
407             If \p key is not in the list and \p bAllowInsert is \p true,
408
409             the function inserts a new item.
410             Otherwise, the function returns an iterator pointing to the item found.
411
412             Returns <tt> std::pair<iterator, bool> </tt> where \p first is an iterator pointing to
413             item found or inserted, \p second is true if new item has been added or \p false if the item
414             already is in the list.
415         */
416         template <typename K>
417         std::pair<iterator, bool> update( K const& key, bool bAllowInsert = true )
418         {
419             std::pair< node_type *, bool > ret = update_at( head(), key, bAllowInsert );
420             return std::make_pair( node_to_iterator( ret.first ), ret.second );
421         }
422         //@cond
423         template <typename K>
424         CDS_DEPRECATED("ensure() is deprecated, use update()")
425         std::pair<iterator, bool> ensure( K const& key )
426         {
427             return update( key );
428         }
429         //@endcond
430
431         /// Inserts data of type \ref mapped_type constructed with <tt>std::forward<Args>(args)...</tt>
432         /**
433             Returns an iterator pointed to inserted value, or \p end() if inserting is failed
434         */
435         template <typename K, typename... Args>
436         iterator emplace( K&& key, Args&&... args )
437         {
438             return node_to_iterator( emplace_at( head(), std::forward<K>(key), std::forward<Args>(args)... ));
439         }
440
441         /// Checks whether the list contains \p key
442         /**
443             The function searches the item with key equal to \p key
444             and returns an iterator pointed to item found and \ref end() otherwise
445         */
446         template <typename Q>
447         iterator contains( Q const& key )
448         {
449             return node_to_iterator( find_at( head(), key, intrusive_key_comparator()));
450         }
451         //@cond
452         template <typename Q>
453         CDS_DEPRECATED("deprecated, use contains()")
454         iterator find( Q const& key )
455         {
456             return contains( key );
457         }
458         //@endcond
459
460         /// Checks whether the list contains \p key using \p pred predicate for searching
461         /**
462             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
463             \p Less functor has the interface like \p std::less.
464             \p pred must imply the same element order as the comparator used for building the list.
465         */
466         template <typename Q, typename Less>
467         iterator contains( Q const& key, Less pred )
468         {
469             CDS_UNUSED( pred );
470             return node_to_iterator( find_at( head(), key, typename maker::template less_wrapper<Less>::type()));
471         }
472         //@cond
473         template <typename Q, typename Less>
474         CDS_DEPRECATED("deprecated, use contains()")
475         iterator find_with( Q const& key, Less pred )
476         {
477             return contains( key, pred );
478         }
479         //@endcond
480
481         /// Check if the list is empty
482         bool empty() const
483         {
484             return base_class::empty();
485         }
486
487         /// Returns list's item count
488         /**
489             The value returned depends on item counter provided by \p Traits. For \p atomicity::empty_item_counter,
490             this function always returns 0.
491
492             @note Even if you use real item counter and it returns 0, this fact does not mean that the list
493             is empty. To check list emptyness use \p empty() method.
494         */
495         size_t size() const
496         {
497             return base_class::size();
498         }
499
500         /// Returns const reference to internal statistics
501         stat const& statistics() const
502         {
503             return base_class::statistics();
504         }
505
506         /// Clears the list
507         void clear()
508         {
509             base_class::clear();
510         }
511
512     protected:
513         //@cond
514         node_type * insert_node_at( head_type& refHead, node_type * pNode )
515         {
516             assert( pNode != nullptr );
517             scoped_node_ptr p( pNode );
518             if ( base_class::insert_at( refHead, *pNode ))
519                 return p.release();
520             return nullptr;
521         }
522
523         template <typename K>
524         node_type * insert_at( head_type& refHead, const K& key )
525         {
526             return insert_node_at( refHead, alloc_node( key ));
527         }
528
529         template <typename K, typename V>
530         node_type * insert_at( head_type& refHead, const K& key, const V& val )
531         {
532             return insert_node_at( refHead, alloc_node( key, val ));
533         }
534
535         template <typename K, typename Func>
536         node_type * insert_with_at( head_type& refHead, const K& key, Func f )
537         {
538             scoped_node_ptr pNode( alloc_node( key ));
539
540             if ( base_class::insert_at( refHead, *pNode )) {
541                 f( pNode->m_Data );
542                 return pNode.release();
543             }
544             return nullptr;
545         }
546
547         template <typename K>
548         std::pair< node_type *, bool > update_at( head_type& refHead, const K& key, bool bAllowInsert )
549         {
550             scoped_node_ptr pNode( alloc_node( key ));
551             node_type * pItemFound = nullptr;
552
553             std::pair<bool, bool> ret = base_class::update_at( refHead, *pNode,
554
555                 [&pItemFound](bool, node_type& item, node_type&){ pItemFound = &item; },
556                 bAllowInsert );
557
558             if ( ret.second )
559                 pNode.release();
560             return std::make_pair( pItemFound, ret.second );
561         }
562
563         template <typename K, typename... Args>
564         node_type * emplace_at( head_type& refHead, K&& key, Args&&... args )
565         {
566             return insert_node_at( refHead, alloc_node( std::forward<K>(key), std::forward<Args>(args)... ));
567         }
568
569         template <typename K, typename Compare>
570         node_type * find_at( head_type& refHead, K const& key, Compare cmp )
571         {
572             return base_class::find_at( refHead, key, cmp );
573         }
574
575         template <typename K>
576         static node_type * alloc_node( const K& key )
577         {
578             return cxx_allocator().New( key );
579         }
580
581         template <typename K, typename V>
582         static node_type * alloc_node( const K& key, const V& val )
583         {
584             return cxx_allocator().New( key, val );
585         }
586
587         template <typename K, typename... Args>
588         static node_type * alloc_node( K&& key, Args&&... args )
589         {
590             return cxx_allocator().MoveNew( std::forward<K>( key ), std::forward<Args>( args )... );
591         }
592
593         static void free_node( node_type * pNode )
594         {
595             cxx_allocator().Delete( pNode );
596         }
597
598         head_type& head()
599         {
600             return base_class::m_pHead;
601         }
602
603         head_type const& head() const
604         {
605             return base_class::m_pHead;
606         }
607
608         iterator node_to_iterator( node_type * pNode )
609         {
610             if ( pNode )
611                 return iterator( *pNode );
612             return end();
613         }
614         //@endcond
615     };
616
617 }} // namespace cds::container
618
619 #endif // #ifndef CDSLIB_CONTAINER_MICHAEL_KVLIST_NOGC_H