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