Remove CDS_EMPLACE_SUPPORT macro and unused code
[libcds.git] / cds / container / striped_map / std_list.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_STRIPED_MAP_STD_LIST_ADAPTER_H
4 #define __CDS_CONTAINER_STRIPED_MAP_STD_LIST_ADAPTER_H
5
6 #include <cds/container/striped_set/adapter.h>
7 #include <cds/ref.h>
8 #include <list>
9 #include <algorithm>    // std::lower_bound
10 #include <utility>      // std::pair
11
12 //@cond
13 namespace cds { namespace container {
14     namespace striped_set {
15
16         // Copy policy for map
17         template <typename K, typename T, typename Alloc>
18         struct copy_item_policy< std::list< std::pair< K const, T >, Alloc > >
19         {
20             typedef std::pair< K const, T>  pair_type;
21             typedef std::list< pair_type, Alloc > list_type;
22             typedef typename list_type::iterator    iterator;
23
24             void operator()( list_type& list, iterator itInsert, iterator itWhat )
25             {
26                 list.insert( itInsert, *itWhat );
27             }
28         };
29
30         // Swap policy for map
31         template <typename K, typename T, typename Alloc>
32         struct swap_item_policy< std::list< std::pair< K const, T >, Alloc > >
33         {
34             typedef std::pair< K const, T>  pair_type;
35             typedef std::list< pair_type, Alloc > list_type;
36             typedef typename list_type::iterator    iterator;
37
38             void operator()( list_type& list, iterator itInsert, iterator itWhat )
39             {
40                 pair_type newVal( itWhat->first, typename pair_type::second_type() );
41                 itInsert = list.insert( itInsert, newVal );
42                 std::swap( itInsert->second, itWhat->second );
43             }
44         };
45
46         // Move policy for map
47         template <typename K, typename T, typename Alloc>
48         struct move_item_policy< std::list< std::pair< K const, T >, Alloc > >
49         {
50             typedef std::pair< K const, T>          pair_type;
51             typedef std::list< pair_type, Alloc >   list_type;
52             typedef typename list_type::iterator    iterator;
53
54             void operator()( list_type& list, iterator itInsert, iterator itWhat )
55             {
56                 list.insert( itInsert, std::move( *itWhat ) );
57             }
58         };
59     } // namespace striped_set
60 }} // namespace cds:container
61
62 namespace cds { namespace intrusive { namespace striped_set {
63
64     /// std::list adapter for hash map bucket
65     template <typename Key, typename T, class Alloc, CDS_SPEC_OPTIONS>
66     class adapt< std::list< std::pair<Key const, T>, Alloc>, CDS_OPTIONS >
67     {
68     public:
69         typedef std::list< std::pair<Key const, T>, Alloc>     container_type          ;   ///< underlying container type
70
71     private:
72         /// Adapted container type
73         class adapted_container: public cds::container::striped_set::adapted_sequential_container
74         {
75         public:
76             typedef typename container_type::value_type     value_type  ;   ///< value type stored in the container
77             typedef typename value_type::first_type         key_type;
78             typedef typename value_type::second_type        mapped_type;
79             typedef typename container_type::iterator       iterator    ;   ///< container iterator
80             typedef typename container_type::const_iterator const_iterator ;    ///< container const iterator
81
82             static bool const has_find_with = true;
83             static bool const has_erase_with = true;
84
85         private:
86             //@cond
87             typedef typename cds::opt::details::make_comparator_from_option_list< value_type, CDS_OPTIONS >::type key_comparator;
88
89
90             typedef typename cds::opt::select<
91                 typename cds::opt::value<
92                     typename cds::opt::find_option<
93                         cds::opt::copy_policy< cds::container::striped_set::move_item >
94                         , CDS_OPTIONS
95                     >::type
96                 >::copy_policy
97                 , cds::container::striped_set::copy_item, cds::container::striped_set::copy_item_policy<container_type>
98                 , cds::container::striped_set::swap_item, cds::container::striped_set::swap_item_policy<container_type>
99                 , cds::container::striped_set::move_item, cds::container::striped_set::move_item_policy<container_type>
100             >::type copy_item;
101
102             struct find_predicate
103             {
104                 bool operator()( value_type const& i1, value_type const& i2) const
105                 {
106                     return key_comparator()( i1.first, i2.first ) < 0;
107                 }
108
109                 template <typename Q>
110                 bool operator()( Q const& i1, value_type const& i2) const
111                 {
112                     return key_comparator()( i1, i2.first ) < 0;
113                 }
114
115                 template <typename Q>
116                 bool operator()( value_type const& i1, Q const& i2) const
117                 {
118                     return key_comparator()( i1.first, i2 ) < 0;
119                 }
120             };
121             //@endcond
122
123         private:
124             //@cond
125             container_type  m_List;
126 #       ifdef __GLIBCXX__
127             // GCC C++ lib bug:
128             // In GCC (at least up to 4.7.x), the complexity of std::list::size() is O(N)
129             // (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49561)
130             size_t          m_nSize ;   // list size
131 #       endif
132             //@endcond
133
134         public:
135             adapted_container()
136 #       ifdef __GLIBCXX__
137                 : m_nSize(0)
138 #       endif
139             {}
140
141             template <typename Q, typename Func>
142             bool insert( const Q& key, Func f )
143             {
144                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
145                 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 ) {
146                     //value_type newItem( key );
147                     it = m_List.insert( it, value_type( key, mapped_type()) );
148                     cds::unref( f )( *it );
149
150 #           ifdef __GLIBCXX__
151                     ++m_nSize;
152 #           endif
153                     return true;
154                 }
155
156                 // key already exists
157                 return false;
158             }
159
160             template <typename K, typename... Args>
161             bool emplace( K&& key, Args&&... args )
162             {
163                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
164                 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 ) {
165                     //value_type newItem( key );
166                     it = m_List.emplace( it, value_type( std::forward<K>(key), std::move( mapped_type( std::forward<Args>(args)...) )) );
167
168 #           ifdef __GLIBCXX__
169                     ++m_nSize;
170 #           endif
171                     return true;
172                 }
173                 return false;
174             }
175
176             template <typename Q, typename Func>
177             std::pair<bool, bool> ensure( const Q& key, Func func )
178             {
179                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
180                 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 ) {
181                     // insert new
182                     value_type newItem( key, mapped_type() );
183                     it = m_List.insert( it, newItem );
184                     cds::unref( func )( true, *it );
185 #           ifdef __GLIBCXX__
186                     ++m_nSize;
187 #           endif
188                     return std::make_pair( true, true );
189                 }
190                 else {
191                     // already exists
192                     cds::unref( func )( false, *it );
193                     return std::make_pair( true, false );
194                 }
195             }
196
197             template <typename Q, typename Func>
198             bool erase( Q const& key, Func f )
199             {
200                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
201                 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 )
202                     return false;
203
204                 // key exists
205                 cds::unref( f )( *it );
206                 m_List.erase( it );
207 #           ifdef __GLIBCXX__
208                 --m_nSize;
209 #           endif
210
211                 return true;
212             }
213
214             template <typename Q, typename Less, typename Func>
215             bool erase( Q const& key, Less pred, Func f )
216             {
217                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, pred );
218                 if ( it == m_List.end() || pred( key, it->first ) || pred( it->first, key ) )
219                     return false;
220
221                 // key exists
222                 cds::unref( f )( *it );
223                 m_List.erase( it );
224 #           ifdef __GLIBCXX__
225                 --m_nSize;
226 #           endif
227
228                 return true;
229             }
230
231             template <typename Q, typename Func>
232             bool find( Q& val, Func f )
233             {
234                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, find_predicate() );
235                 if ( it == m_List.end() || key_comparator()( val, it->first ) != 0 )
236                     return false;
237
238                 // key exists
239                 cds::unref( f )( *it, val );
240                 return true;
241             }
242
243             template <typename Q, typename Less, typename Func>
244             bool find( Q& val, Less pred, Func f )
245             {
246                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, pred );
247                 if ( it == m_List.end() || pred( val, it->first ) || pred( it->first, val ) )
248                     return false;
249
250                 // key exists
251                 cds::unref( f )( *it, val );
252                 return true;
253             }
254
255             void clear()
256             {
257                 m_List.clear();
258             }
259
260             iterator begin()                { return m_List.begin(); }
261             const_iterator begin() const    { return m_List.begin(); }
262             iterator end()                  { return m_List.end(); }
263             const_iterator end() const      { return m_List.end(); }
264
265             void move_item( adapted_container& /*from*/, iterator itWhat )
266             {
267                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), *itWhat, find_predicate() );
268                 assert( it == m_List.end() || key_comparator()( itWhat->first, it->first ) != 0 );
269
270                 copy_item()( m_List, it, itWhat );
271 #           ifdef __GLIBCXX__
272                 ++m_nSize;
273 #           endif
274             }
275
276             size_t size() const
277             {
278 #           ifdef __GLIBCXX__
279                 return m_nSize;
280 #           else
281                 return m_List.size();
282 #           endif
283
284             }
285         };
286
287     public:
288         typedef adapted_container type ; ///< Result of \p adapt metafunction
289
290     };
291 }}} // namespace cds::intrusive::striped_set
292
293 //@endcond
294
295 #endif // #ifndef __CDS_CONTAINER_STRIPED_MAP_STD_LIST_ADAPTER_H