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