Remove CDS_RVALUE_SUPPORT, CDS_MOVE_SEMANTICS_SUPPORT macros and emulating 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 #           ifdef CDS_EMPLACE_SUPPORT
161             template <typename K, typename... Args>
162             bool emplace( K&& key, Args&&... args )
163             {
164                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
165                 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 ) {
166                     //value_type newItem( key );
167                     it = m_List.emplace( it, value_type( std::forward<K>(key), std::move( mapped_type( std::forward<Args>(args)...) )) );
168
169 #           ifdef __GLIBCXX__
170                     ++m_nSize;
171 #           endif
172                     return true;
173                 }
174                 return false;
175             }
176 #           endif
177
178             template <typename Q, typename Func>
179             std::pair<bool, bool> ensure( const Q& key, Func func )
180             {
181                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
182                 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 ) {
183                     // insert new
184                     value_type newItem( key, mapped_type() );
185                     it = m_List.insert( it, newItem );
186                     cds::unref( func )( true, *it );
187 #           ifdef __GLIBCXX__
188                     ++m_nSize;
189 #           endif
190                     return std::make_pair( true, true );
191                 }
192                 else {
193                     // already exists
194                     cds::unref( func )( false, *it );
195                     return std::make_pair( true, false );
196                 }
197             }
198
199             template <typename Q, typename Func>
200             bool erase( Q const& key, Func f )
201             {
202                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
203                 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 )
204                     return false;
205
206                 // key exists
207                 cds::unref( f )( *it );
208                 m_List.erase( it );
209 #           ifdef __GLIBCXX__
210                 --m_nSize;
211 #           endif
212
213                 return true;
214             }
215
216             template <typename Q, typename Less, typename Func>
217             bool erase( Q const& key, Less pred, Func f )
218             {
219                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, pred );
220                 if ( it == m_List.end() || pred( key, it->first ) || pred( it->first, key ) )
221                     return false;
222
223                 // key exists
224                 cds::unref( f )( *it );
225                 m_List.erase( it );
226 #           ifdef __GLIBCXX__
227                 --m_nSize;
228 #           endif
229
230                 return true;
231             }
232
233             template <typename Q, typename Func>
234             bool find( Q& val, Func f )
235             {
236                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, find_predicate() );
237                 if ( it == m_List.end() || key_comparator()( val, it->first ) != 0 )
238                     return false;
239
240                 // key exists
241                 cds::unref( f )( *it, val );
242                 return true;
243             }
244
245             template <typename Q, typename Less, typename Func>
246             bool find( Q& val, Less pred, Func f )
247             {
248                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, pred );
249                 if ( it == m_List.end() || pred( val, it->first ) || pred( it->first, val ) )
250                     return false;
251
252                 // key exists
253                 cds::unref( f )( *it, val );
254                 return true;
255             }
256
257             void clear()
258             {
259                 m_List.clear();
260             }
261
262             iterator begin()                { return m_List.begin(); }
263             const_iterator begin() const    { return m_List.begin(); }
264             iterator end()                  { return m_List.end(); }
265             const_iterator end() const      { return m_List.end(); }
266
267             void move_item( adapted_container& /*from*/, iterator itWhat )
268             {
269                 iterator it = std::lower_bound( m_List.begin(), m_List.end(), *itWhat, find_predicate() );
270                 assert( it == m_List.end() || key_comparator()( itWhat->first, it->first ) != 0 );
271
272                 copy_item()( m_List, it, itWhat );
273 #           ifdef __GLIBCXX__
274                 ++m_nSize;
275 #           endif
276             }
277
278             size_t size() const
279             {
280 #           ifdef __GLIBCXX__
281                 return m_nSize;
282 #           else
283                 return m_List.size();
284 #           endif
285
286             }
287         };
288
289     public:
290         typedef adapted_container type ; ///< Result of \p adapt metafunction
291
292     };
293 }}} // namespace cds::intrusive::striped_set
294
295 //@endcond
296
297 #endif // #ifndef __CDS_CONTAINER_STRIPED_MAP_STD_LIST_ADAPTER_H