Added copyright and license
[libcds.git] / cds / container / impl / feldman_hashset.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_IMPL_FELDMAN_HASHSET_H
32 #define CDSLIB_CONTAINER_IMPL_FELDMAN_HASHSET_H
33
34 #include <cds/intrusive/impl/feldman_hashset.h>
35 #include <cds/container/details/feldman_hashset_base.h>
36
37 namespace cds { namespace container {
38
39     /// Hash set based on multi-level array
40     /** @ingroup cds_nonintrusive_set
41         @anchor cds_container_FeldmanHashSet_hp
42
43         Source:
44         - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays:
45                  Wait-free Extensible Hash Maps"
46
47         [From the paper] The hardest problem encountered while developing a parallel hash map is how to perform
48         a global resize, the process of redistributing the elements in a hash map that occurs when adding new
49         buckets. The negative impact of blocking synchronization is multiplied during a global resize, because all
50         threads will be forced to wait on the thread that is performing the involved process of resizing the hash map
51         and redistributing the elements. \p %FeldmanHashSet implementation avoids global resizes through new array
52         allocation. By allowing concurrent expansion this structure is free from the overhead of an explicit resize,
53         which facilitates concurrent operations.
54
55         The presented design includes dynamic hashing, the use of sub-arrays within the hash map data structure;
56         which, in combination with <b>perfect hashing</b>, means that each element has a unique final, as well as current, position.
57         It is important to note that the perfect hash function required by our hash map is trivial to realize as
58         any hash function that permutes the bits of the key is suitable. This is possible because of our approach
59         to the hash function; we require that it produces hash values that are equal in size to that of the key.
60         We know that if we expand the hash map a fixed number of times there can be no collision as duplicate keys
61         are not provided for in the standard semantics of a hash map.
62
63         \p %FeldmanHashSet is a multi-level array which has an internal structure similar to a tree:
64         @image html feldman_hashset.png
65         The multi-level array differs from a tree in that each position on the tree could hold an array of nodes or a single node.
66         A position that holds a single node is a \p dataNode which holds the hash value of a key and the value that is associated
67         with that key; it is a simple struct holding two variables. A \p dataNode in the multi-level array could be marked.
68         A \p markedDataNode refers to a pointer to a \p dataNode that has been bitmarked at the least significant bit (LSB)
69         of the pointer to the node. This signifies that this \p dataNode is contended. An expansion must occur at this node;
70         any thread that sees this \p markedDataNode will try to replace it with an \p arrayNode; which is a position that holds
71         an array of nodes. The pointer to an \p arrayNode is differentiated from that of a pointer to a \p dataNode by a bitmark
72         on the second-least significant bit.
73
74         \p %FeldmanHashSet multi-level array is similar to a tree in that we keep a pointer to the root, which is a memory array
75         called \p head. The length of the \p head memory array is unique, whereas every other \p arrayNode has a uniform length;
76         a normal \p arrayNode has a fixed power-of-two length equal to the binary logarithm of a variable called \p arrayLength.
77         The maximum depth of the tree, \p maxDepth, is the maximum number of pointers that must be followed to reach any node.
78         We define \p currentDepth as the number of memory arrays that we need to traverse to reach the \p arrayNode on which
79         we need to operate; this is initially one, because of \p head.
80
81         That approach to the structure of the hash set uses an extensible hashing scheme; <b> the hash value is treated as a bit
82         string</b> and rehash incrementally.
83
84         @note Two important things you should keep in mind when you're using \p %FeldmanHashSet:
85         - all keys must be fixed-size. It means that you cannot use \p std::string as a key for \p %FeldmanHashSet.
86           Instead, for the strings you should use well-known hashing algorithms like <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
87           <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
88           or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> and so on, which
89           converts variable-length strings to fixed-length bit-strings, and use that hash as a key in \p %FeldmanHashSet.
90         - \p %FeldmanHashSet uses a perfect hashing. It means that if two different keys, for example, of type \p std::string,
91           have identical hash then you cannot insert both that keys in the set. \p %FeldmanHashSet does not maintain the key,
92           it maintains its fixed-size hash value.
93
94         The set supports @ref cds_container_FeldmanHashSet_iterators "bidirectional thread-safe iterators".
95
96         Template parameters:
97         - \p GC - safe memory reclamation schema. Can be \p gc::HP, \p gc::DHP or one of \ref cds_urcu_type "RCU type"
98         - \p T - a value type to be stored in the set
99         - \p Traits - type traits, the structure based on \p feldman_hashset::traits or result of \p feldman_hashset::make_traits metafunction.
100             \p Traits is the mandatory argument because it has one mandatory type - an @ref feldman_hashset::traits::hash_accessor "accessor"
101             to hash value of \p T. The set algorithm does not calculate that hash value.
102
103         There are several specializations of \p %FeldmanHashSet for each \p GC. You should include:
104         - <tt><cds/container/feldman_hashset_hp.h></tt> for \p gc::HP garbage collector
105         - <tt><cds/container/feldman_hashset_dhp.h></tt> for \p gc::DHP garbage collector
106         - <tt><cds/container/feldman_hashset_rcu.h></tt> for \ref cds_intrusive_FeldmanHashSet_rcu "RCU type". RCU specialization
107             has a slightly different interface.
108     */
109     template <
110         class GC
111         , typename T
112 #ifdef CDS_DOXYGEN_INVOKED
113         , class Traits = feldman_hashset::traits
114 #else
115         , class Traits
116 #endif
117     >
118     class FeldmanHashSet
119 #ifdef CDS_DOXYGEN_INVOKED
120         : protected cds::intrusive::FeldmanHashSet< GC, T, Traits >
121 #else
122         : protected cds::container::details::make_feldman_hashset< GC, T, Traits >::type
123 #endif
124     {
125         //@cond
126         typedef cds::container::details::make_feldman_hashset< GC, T, Traits > maker;
127         typedef typename maker::type base_class;
128         //@endcond
129
130     public:
131         typedef GC      gc;         ///< Garbage collector
132         typedef T       value_type; ///< type of value stored in the set
133         typedef Traits  traits;     ///< Traits template parameter, see \p feldman_hashset::traits
134
135         typedef typename base_class::hash_accessor hash_accessor; ///< Hash accessor functor
136         typedef typename base_class::hash_type hash_type; ///< Hash type deduced from \p hash_accessor return type
137         typedef typename base_class::hash_comparator hash_comparator; ///< hash compare functor based on \p opt::compare and \p opt::less option setter
138
139         typedef typename traits::item_counter   item_counter;   ///< Item counter type
140         typedef typename traits::allocator      allocator;      ///< Element allocator
141         typedef typename traits::node_allocator node_allocator; ///< Array node allocator
142         typedef typename traits::memory_model   memory_model;   ///< Memory model
143         typedef typename traits::back_off       back_off;       ///< Backoff strategy
144         typedef typename traits::stat           stat;           ///< Internal statistics type
145
146         typedef typename gc::template guarded_ptr< value_type > guarded_ptr; ///< Guarded pointer
147
148         /// Count of hazard pointers required
149         static CDS_CONSTEXPR size_t const c_nHazardPtrCount = base_class::c_nHazardPtrCount;
150
151         typedef typename base_class::iterator               iterator;       ///< @ref cds_container_FeldmanHashSet_iterators "bidirectional iterator" type
152         typedef typename base_class::const_iterator         const_iterator; ///< @ref cds_container_FeldmanHashSet_iterators "bidirectional const iterator" type
153         typedef typename base_class::reverse_iterator       reverse_iterator;       ///< @ref cds_container_FeldmanHashSet_iterators "bidirectional reverse iterator" type
154         typedef typename base_class::const_reverse_iterator const_reverse_iterator; ///< @ref cds_container_FeldmanHashSet_iterators "bidirectional reverse const iterator" type
155
156     protected:
157         //@cond
158         typedef typename maker::cxx_node_allocator cxx_node_allocator;
159         typedef std::unique_ptr< value_type, typename maker::node_disposer > scoped_node_ptr;
160         //@endcond
161
162     public:
163         /// Creates empty set
164         /**
165             @param head_bits: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
166             @param array_bits: 2<sup>array_bits</sup> specifies the size of array node, minimum is 2.
167
168             Equation for \p head_bits and \p array_bits:
169             \code
170             sizeof(hash_type) * 8 == head_bits + N * array_bits
171             \endcode
172             where \p N is multi-level array depth.
173         */
174         FeldmanHashSet( size_t head_bits = 8, size_t array_bits = 4 )
175             : base_class( head_bits, array_bits )
176         {}
177
178         /// Destructs the set and frees all data
179         ~FeldmanHashSet()
180         {}
181
182         /// Inserts new element
183         /**
184             The function creates an element with copy of \p val value and then inserts it into the set.
185
186             The type \p Q should contain as minimum the complete hash for the element.
187             The object of \ref value_type should be constructible from a value of type \p Q.
188             In trivial case, \p Q is equal to \ref value_type.
189
190             Returns \p true if \p val is inserted into the set, \p false otherwise.
191         */
192         template <typename Q>
193         bool insert( Q const& val )
194         {
195             scoped_node_ptr sp( cxx_node_allocator().New( val ));
196             if ( base_class::insert( *sp )) {
197                 sp.release();
198                 return true;
199             }
200             return false;
201         }
202
203         /// Inserts new element
204         /**
205             The function allows to split creating of new item into two part:
206             - create item with key only
207             - insert new item into the set
208             - if inserting is success, calls \p f functor to initialize value-fields of \p val.
209
210             The functor signature is:
211             \code
212                 void func( value_type& val );
213             \endcode
214             where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
215             \p val no any other changes could be made on this set's item by concurrent threads.
216             The user-defined functor is called only if the inserting is success.
217         */
218         template <typename Q, typename Func>
219         bool insert( Q const& val, Func f )
220         {
221             scoped_node_ptr sp( cxx_node_allocator().New( val ));
222             if ( base_class::insert( *sp, f )) {
223                 sp.release();
224                 return true;
225             }
226             return false;
227         }
228
229         /// Updates the element
230         /**
231             The operation performs inserting or replacing with lock-free manner.
232
233             If the \p val key not found in the set, then the new item created from \p val
234             will be inserted into the set iff \p bInsert is \p true.
235             Otherwise, if \p val is found, it is replaced with new item created from \p val
236             and previous item is disposed.
237             In both cases \p func functor is called.
238
239             The functor \p Func signature:
240             \code
241                 struct my_functor {
242                     void operator()( value_type& cur, value_type * prev );
243                 };
244             \endcode
245             where:
246             - \p cur - current element
247             - \p prev - pointer to previous element with such hash. \p prev is \p nullptr
248                  if \p cur was just inserted.
249
250             The functor may change non-key fields of the \p item; however, \p func must guarantee
251             that during changing no any other modifications could be made on this item by concurrent threads.
252
253             Returns <tt> std::pair<bool, bool> </tt> where \p first is \p true if operation is successfull,
254             i.e. the item has been inserted or updated,
255             \p second is \p true if the new item has been added or \p false if the item with key equal to \p val
256             already exists.
257         */
258         template <typename Q, typename Func>
259         std::pair<bool, bool> update( Q const& val, Func func, bool bInsert = true )
260         {
261             scoped_node_ptr sp( cxx_node_allocator().New( val ));
262             std::pair<bool, bool> bRes = base_class::do_update( *sp, func, bInsert );
263             if ( bRes.first )
264                 sp.release();
265             return bRes;
266         }
267
268         /// Inserts data of type \p value_type created in-place from <tt>std::forward<Args>(args)...</tt>
269         /**
270             Returns \p true if inserting successful, \p false otherwise.
271         */
272         template <typename... Args>
273         bool emplace( Args&&... args )
274         {
275             scoped_node_ptr sp( cxx_node_allocator().New( std::forward<Args>(args)... ));
276             if ( base_class::insert( *sp )) {
277                 sp.release();
278                 return true;
279             }
280             return false;
281         }
282
283         /// Deletes the item from the set
284         /**
285             The function searches \p hash in the set,
286             deletes the item found, and returns \p true.
287             If that item is not found the function returns \p false.
288         */
289         bool erase( hash_type const& hash )
290         {
291             return base_class::erase( hash );
292         }
293
294         /// Deletes the item from the set
295         /**
296             The function searches \p hash in the set,
297             call \p f functor with item found, and deltes the element from the set.
298
299             The \p Func interface is
300             \code
301             struct functor {
302                 void operator()( value_type& item );
303             };
304             \endcode
305
306             If \p hash is not found the function returns \p false.
307         */
308         template <typename Func>
309         bool erase( hash_type const& hash, Func f )
310         {
311             return base_class::erase( hash, f );
312         }
313
314         /// Deletes the item pointed by iterator \p iter
315         /**
316             Returns \p true if the operation is successful, \p false otherwise.
317
318             The function does not invalidate the iterator, it remains valid and can be used for further traversing.
319         */
320         bool erase_at( iterator const& iter )
321         {
322             return base_class::erase_at( iter );
323         }
324         //@cond
325         bool erase_at( reverse_iterator const& iter )
326         {
327             return base_class::erase_at( iter );
328         }
329         //@endcond
330
331         /// Extracts the item with specified \p hash
332         /**
333             The function searches \p hash in the set,
334             unlinks it from the set, and returns a guarded pointer to the item extracted.
335             If \p hash is not found the function returns an empty guarded pointer.
336
337             The item returned is reclaimed by garbage collector \p GC
338             when returned \ref guarded_ptr object to be destroyed or released.
339             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
340
341             Usage:
342             \code
343             typedef cds::container::FeldmanHashSet< your_template_args > my_set;
344             my_set theSet;
345             // ...
346             {
347                 my_set::guarded_ptr gp( theSet.extract( 5 ));
348                 if ( gp ) {
349                     // Deal with gp
350                     // ...
351                 }
352                 // Destructor of gp releases internal HP guard
353             }
354             \endcode
355         */
356         guarded_ptr extract( hash_type const& hash )
357         {
358             return base_class::extract( hash );
359         }
360
361         /// Finds an item by it's \p hash
362         /**
363             The function searches the item by \p hash and calls the functor \p f for item found.
364             The interface of \p Func functor is:
365             \code
366             struct functor {
367                 void operator()( value_type& item );
368             };
369             \endcode
370             where \p item is the item found.
371
372             The functor may change non-key fields of \p item. Note that the functor is only guarantee
373             that \p item cannot be disposed during the functor is executing.
374             The functor does not serialize simultaneous access to the set's \p item. If such access is
375             possible you must provide your own synchronization schema on item level to prevent unsafe item modifications.
376
377             The function returns \p true if \p hash is found, \p false otherwise.
378         */
379         template <typename Func>
380         bool find( hash_type const& hash, Func f )
381         {
382             return base_class::find( hash, f );
383         }
384
385         /// Checks whether the set contains \p hash
386         /**
387             The function searches the item by its \p hash
388             and returns \p true if it is found, or \p false otherwise.
389         */
390         bool contains( hash_type const& hash )
391         {
392             return base_class::contains( hash );
393         }
394
395         /// Finds an item by it's \p hash and returns the item found
396         /**
397             The function searches the item by its \p hash
398             and returns the guarded pointer to the item found.
399             If \p hash is not found the function returns an empty \p guarded_ptr.
400
401             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
402
403             Usage:
404             \code
405             typedef cds::container::FeldmanHashSet< your_template_params >  my_set;
406             my_set theSet;
407             // ...
408             {
409                 my_set::guarded_ptr gp( theSet.get( 5 ));
410                 if ( theSet.get( 5 )) {
411                     // Deal with gp
412                     //...
413                 }
414                 // Destructor of guarded_ptr releases internal HP guard
415             }
416             \endcode
417         */
418         guarded_ptr get( hash_type const& hash )
419         {
420             return base_class::get( hash );
421         }
422
423         /// Clears the set (non-atomic)
424         /**
425             The function unlink all data node from the set.
426             The function is not atomic but is thread-safe.
427             After \p %clear() the set may not be empty because another threads may insert items.
428         */
429         void clear()
430         {
431             base_class::clear();
432         }
433
434         /// Checks if the set is empty
435         /**
436             Emptiness is checked by item counting: if item count is zero then the set is empty.
437             Thus, the correct item counting feature is an important part of the set implementation.
438         */
439         bool empty() const
440         {
441             return base_class::empty();
442         }
443
444         /// Returns item count in the set
445         size_t size() const
446         {
447             return base_class::size();
448         }
449
450         /// Returns const reference to internal statistics
451         stat const& statistics() const
452         {
453             return base_class::statistics();
454         }
455
456         /// Returns the size of head node
457         size_t head_size() const
458         {
459             return base_class::head_size();
460         }
461
462         /// Returns the size of the array node
463         size_t array_node_size() const
464         {
465             return base_class::array_node_size();
466         }
467
468         /// Collects tree level statistics into \p stat
469         /** @copydetails cds::intrusive::FeldmanHashSet::get_level_statistics
470         */
471         void get_level_statistics(std::vector< feldman_hashset::level_statistics>& stat) const
472         {
473             base_class::get_level_statistics(stat);
474         }
475
476     public:
477     ///@name Thread-safe iterators
478         /** @anchor cds_container_FeldmanHashSet_iterators
479             The set supports thread-safe iterators: you may iterate over the set in multi-threaded environment.
480             It is guaranteed that the iterators will remain valid even if another thread deletes the node the iterator points to:
481             Hazard Pointer embedded into the iterator object protects the node from physical reclamation.
482
483             @note Since the iterator object contains hazard pointer that is a thread-local resource,
484             the iterator should not be passed to another thread.
485
486             Each iterator object supports the common interface:
487             - dereference operators:
488                 @code
489                 value_type [const] * operator ->() noexcept
490                 value_type [const] & operator *() noexcept
491                 @endcode
492             - pre-increment and pre-decrement. Post-operators is not supported
493             - equality operators <tt>==</tt> and <tt>!=</tt>.
494                 Iterators are equal iff they point to the same cell of the same array node.
495                 Note that for two iterators \p it1 and \p it2, the conditon <tt> it1 == it2 </tt>
496                 does not entail <tt> &(*it1) == &(*it2) </tt>
497             - helper member function \p release() that clears internal hazard pointer.
498                 After \p release() the iterator points to \p nullptr but it still remain valid: further iterating is possible.
499
500             During iteration you may safely erase any item from the set;
501             @ref erase_at() function call doesn't invalidate any iterator.
502             If some iterator points to the item to be erased, that item is not deleted immediately
503             but only after that iterator will be advanced forward or backward.
504
505             @note It is possible the item can be iterated more that once, for example, if an iterator points to the item
506             in array node that is being splitted.
507         */
508     ///@{
509
510         /// Returns an iterator to the beginning of the set
511         iterator begin()
512         {
513             return base_class::begin();
514         }
515
516         /// Returns an const iterator to the beginning of the set
517         const_iterator begin() const
518         {
519             return base_class::begin();
520         }
521
522         /// Returns an const iterator to the beginning of the set
523         const_iterator cbegin()
524         {
525             return base_class::cbegin();
526         }
527
528         /// Returns an iterator to the element following the last element of the set. This element acts as a placeholder; attempting to access it results in undefined behavior.
529         iterator end()
530         {
531             return base_class::end();
532         }
533
534         /// Returns a const iterator to the element following the last element of the set. This element acts as a placeholder; attempting to access it results in undefined behavior.
535         const_iterator end() const
536         {
537             return base_class::end();
538         }
539
540         /// Returns a const iterator to the element following the last element of the set. This element acts as a placeholder; attempting to access it results in undefined behavior.
541         const_iterator cend()
542         {
543             return base_class::cend();
544         }
545
546         /// Returns a reverse iterator to the first element of the reversed set
547         reverse_iterator rbegin()
548         {
549             return base_class::rbegin();
550         }
551
552         /// Returns a const reverse iterator to the first element of the reversed set
553         const_reverse_iterator rbegin() const
554         {
555             return base_class::rbegin();
556         }
557
558         /// Returns a const reverse iterator to the first element of the reversed set
559         const_reverse_iterator crbegin()
560         {
561             return base_class::crbegin();
562         }
563
564         /// Returns a reverse iterator to the element following the last element of the reversed set
565         /**
566             It corresponds to the element preceding the first element of the non-reversed container.
567             This element acts as a placeholder, attempting to access it results in undefined behavior.
568         */
569         reverse_iterator rend()
570         {
571             return base_class::rend();
572         }
573
574         /// Returns a const reverse iterator to the element following the last element of the reversed set
575         /**
576             It corresponds to the element preceding the first element of the non-reversed container.
577             This element acts as a placeholder, attempting to access it results in undefined behavior.
578         */
579         const_reverse_iterator rend() const
580         {
581             return base_class::rend();
582         }
583
584         /// Returns a const reverse iterator to the element following the last element of the reversed set
585         /**
586             It corresponds to the element preceding the first element of the non-reversed container.
587             This element acts as a placeholder, attempting to access it results in undefined behavior.
588         */
589         const_reverse_iterator crend()
590         {
591             return base_class::crend();
592         }
593     ///@}
594     };
595
596 }} // namespace cds::container
597
598 #endif // #ifndef CDSLIB_CONTAINER_IMPL_FELDMAN_HASHSET_H