Added copyright and license
[libcds.git] / cds / container / striped_set / std_hash_set.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_STRIPED_SET_STD_HASH_SET_ADAPTER_H
32 #define CDSLIB_CONTAINER_STRIPED_SET_STD_HASH_SET_ADAPTER_H
33
34 #include <cds/container/striped_set/adapter.h>
35 #include <unordered_set>
36
37 //@cond
38 namespace cds { namespace container {
39     namespace striped_set {
40
41         // Copy policy for std::unordered_set
42         template <typename T, typename Hash, typename Pred, typename Alloc>
43         struct copy_item_policy< std::unordered_set< T, Hash, Pred, Alloc > >
44         {
45             typedef std::unordered_set< T, Hash, Pred, Alloc > set_type;
46             typedef typename set_type::iterator iterator;
47
48             void operator()( set_type& set, iterator itWhat )
49             {
50                 set.insert( *itWhat );
51             }
52         };
53
54         template <typename T, typename Hash, typename Pred, typename Alloc>
55         struct swap_item_policy< std::unordered_set< T, Hash, Pred, Alloc > >: public copy_item_policy< std::unordered_set< T, Hash, Pred, Alloc > >
56         {};
57
58         // Move policy for std::unordered_set
59         template <typename T, typename Hash, typename Pred, typename Alloc>
60         struct move_item_policy< std::unordered_set< T, Hash, Pred, Alloc > >
61         {
62             typedef std::unordered_set< T, Hash, Pred, Alloc > set_type;
63             typedef typename set_type::iterator iterator;
64
65             void operator()( set_type& set, iterator itWhat )
66             {
67                 set.insert( std::move( *itWhat ) );
68             }
69         };
70
71     }   // namespace striped_set
72 }} // namespace cds::container
73
74 namespace cds { namespace intrusive { namespace striped_set {
75     /// std::unordered_set  adapter for hash set bucket
76     template <typename T, class Hash, class Pred, class Alloc, typename... Options>
77     class adapt< std::unordered_set<T, Hash, Pred, Alloc>, Options... >
78     {
79     public:
80         typedef std::unordered_set<T, Hash, Pred, Alloc>  container_type  ;   ///< underlying container type
81
82     private:
83         /// Adapted container type
84         class adapted_container: public cds::container::striped_set::adapted_container
85         {
86         public:
87             typedef typename container_type::value_type value_type  ;   ///< value type stored in the container
88             typedef typename container_type::iterator      iterator ;   ///< container iterator
89             typedef typename container_type::const_iterator const_iterator ;    ///< container const iterator
90
91             static bool const has_find_with = false;
92             static bool const has_erase_with = false;
93
94         private:
95             //@cond
96             typedef typename cds::opt::select<
97                 typename cds::opt::value<
98                     typename cds::opt::find_option<
99                         cds::opt::copy_policy< cds::container::striped_set::move_item >
100                         , Options...
101                     >::type
102                 >::copy_policy
103                 , cds::container::striped_set::copy_item, cds::container::striped_set::copy_item_policy<container_type>
104                 , cds::container::striped_set::swap_item, cds::container::striped_set::swap_item_policy<container_type> // not defined
105                 , cds::container::striped_set::move_item, cds::container::striped_set::move_item_policy<container_type>
106             >::type copy_item;
107             //@endcond
108
109         private:
110             //@cond
111             container_type  m_Set;
112             //@endcond
113
114         public:
115             template <typename Q, typename Func>
116             bool insert( const Q& val, Func f )
117             {
118                 std::pair<iterator, bool> res = m_Set.insert( value_type(val) );
119                 if ( res.second )
120                     f( const_cast<value_type&>(*res.first) );
121                 return res.second;
122             }
123
124             template <typename... Args>
125             bool emplace( Args&&... args )
126             {
127                 std::pair<iterator, bool> res = m_Set.emplace( std::forward<Args>(args)... );
128                 return res.second;
129             }
130
131             template <typename Q, typename Func>
132             std::pair<bool, bool> update( const Q& val, Func func, bool bAllowInsert )
133             {
134                 if ( bAllowInsert ) {
135                     std::pair<iterator, bool> res = m_Set.insert( value_type(val) );
136                     func( res.second, const_cast<value_type&>(*res.first), val );
137                     return std::make_pair( true, res.second );
138                 }
139                 else {
140                     auto it = m_Set.find( value_type(val));
141                     if ( it == m_Set.end() )
142                         return std::make_pair( false, false );
143
144                     func( false, const_cast<value_type&>(*it), val );
145                     return std::make_pair( true, false );
146                 }
147             }
148
149             template <typename Q, typename Func>
150             bool erase( const Q& key, Func f )
151             {
152                 const_iterator it = m_Set.find( value_type(key) );
153                 if ( it == m_Set.end() )
154                     return false;
155                 f( const_cast<value_type&>(*it) );
156                 m_Set.erase( it );
157                 return true;
158             }
159
160             template <typename Q, typename Func>
161             bool find( Q& val, Func f )
162             {
163                 iterator it = m_Set.find( value_type(val) );
164                 if ( it == m_Set.end() )
165                     return false;
166                 f( const_cast<value_type&>(*it), val );
167                 return true;
168             }
169
170             /// Clears the container
171             void clear()
172             {
173                 m_Set.clear();
174             }
175
176             iterator begin()                { return m_Set.begin(); }
177             const_iterator begin() const    { return m_Set.begin(); }
178             iterator end()                  { return m_Set.end(); }
179             const_iterator end() const      { return m_Set.end(); }
180
181             void move_item( adapted_container& /*from*/, iterator itWhat )
182             {
183                 assert( m_Set.find( *itWhat ) == m_Set.end() );
184                 copy_item()( m_Set, itWhat );
185             }
186
187             size_t size() const
188             {
189                 return m_Set.size();
190             }
191         };
192
193     public:
194         typedef adapted_container type ; ///< Result of \p adapt metafunction
195     };
196 }}} // namespace cds::intrusive::striped_set
197
198
199 //@endcond
200
201 #endif  // #ifndef CDSLIB_CONTAINER_STRIPED_SET_STD_HASH_SET_ADAPTER_H