3 #ifndef __CDS_CONTAINER_STRIPED_MAP_BOOST_LIST_ADAPTER_H
4 #define __CDS_CONTAINER_STRIPED_MAP_BOOST_LIST_ADAPTER_H
6 #include <boost/version.hpp>
7 #if BOOST_VERSION < 104800
8 # error "For boost::container::list you must use boost 1.48 or above"
11 #include <cds/container/striped_set/adapter.h>
13 #include <boost/container/list.hpp>
14 #include <algorithm> // std::lower_bound
15 #include <utility> // std::pair
18 namespace cds { namespace container {
19 namespace striped_set {
21 // Copy policy for map
22 template <typename K, typename T, typename Alloc>
23 struct copy_item_policy< boost::container::list< std::pair< K const, T >, Alloc > >
25 typedef std::pair< K const, T> pair_type;
26 typedef boost::container::list< pair_type, Alloc > list_type;
27 typedef typename list_type::iterator iterator;
29 void operator()( list_type& list, iterator itInsert, iterator itWhat )
31 list.insert( itInsert, *itWhat );
35 // Swap policy for map
36 template <typename K, typename T, typename Alloc>
37 struct swap_item_policy< boost::container::list< std::pair< K const, T >, Alloc > >
39 typedef std::pair< K const, T> pair_type;
40 typedef boost::container::list< pair_type, Alloc > list_type;
41 typedef typename list_type::iterator iterator;
43 void operator()( list_type& list, iterator itInsert, iterator itWhat )
45 pair_type newVal( itWhat->first, typename pair_type::second_type() );
46 itInsert = list.insert( itInsert, newVal );
47 std::swap( itInsert->second, itWhat->second );
51 #ifdef CDS_MOVE_SEMANTICS_SUPPORT
52 // Move policy for map
53 template <typename K, typename T, typename Alloc>
54 struct move_item_policy< boost::container::list< std::pair< K const, T >, Alloc > >
56 typedef std::pair< K const, T> pair_type;
57 typedef boost::container::list< pair_type, Alloc > list_type;
58 typedef typename list_type::iterator iterator;
60 void operator()( list_type& list, iterator itInsert, iterator itWhat )
62 list.insert( itInsert, std::move( *itWhat ) );
66 } // namespace striped_set
67 }} // namespace cds:container
69 namespace cds { namespace intrusive { namespace striped_set {
71 /// boost::container::list adapter for hash map bucket
72 template <typename Key, typename T, class Alloc, CDS_SPEC_OPTIONS>
73 class adapt< boost::container::list< std::pair<Key const, T>, Alloc>, CDS_OPTIONS >
76 typedef boost::container::list< std::pair<Key const, T>, Alloc> container_type ; ///< underlying container type
79 /// Adapted container type
80 class adapted_container: public cds::container::striped_set::adapted_sequential_container
83 typedef typename container_type::value_type value_type ; ///< value type stored in the container
84 typedef typename value_type::first_type key_type;
85 typedef typename value_type::second_type mapped_type;
86 typedef typename container_type::iterator iterator ; ///< container iterator
87 typedef typename container_type::const_iterator const_iterator ; ///< container const iterator
89 static bool const has_find_with = true;
90 static bool const has_erase_with = true;
94 typedef typename cds::opt::details::make_comparator_from_option_list< value_type, CDS_OPTIONS >::type key_comparator;
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 >
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>
105 #ifdef CDS_MOVE_SEMANTICS_SUPPORT
106 , cds::container::striped_set::move_item, cds::container::striped_set::move_item_policy<container_type>
110 struct find_predicate
112 bool operator()( value_type const& i1, value_type const& i2) const
114 return key_comparator()( i1.first, i2.first ) < 0;
117 template <typename Q>
118 bool operator()( Q const& i1, value_type const& i2) const
120 return key_comparator()( i1, i2.first ) < 0;
123 template <typename Q>
124 bool operator()( value_type const& i1, Q const& i2) const
126 return key_comparator()( i1.first, i2 ) < 0;
133 container_type m_List;
140 template <typename Q, typename Func>
141 bool insert( const Q& key, Func f )
143 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
144 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 ) {
145 //value_type newItem( key );
146 it = m_List.insert( it, value_type( key, mapped_type()) );
147 cds::unref( f )( *it );
152 // key already exists
156 # ifdef CDS_EMPLACE_SUPPORT
157 template <typename K, typename... Args>
158 bool emplace( K&& key, Args&&... args )
160 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
161 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 ) {
162 m_List.emplace( it, std::forward<K>(key), std::move( mapped_type( std::forward<Args>(args)... )) );
169 template <typename Q, typename Func>
170 std::pair<bool, bool> ensure( const Q& key, Func func )
172 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
173 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 ) {
175 value_type newItem( key, mapped_type() );
176 it = m_List.insert( it, newItem );
177 cds::unref( func )( true, *it );
179 return std::make_pair( true, true );
183 cds::unref( func )( false, *it );
184 return std::make_pair( true, false );
188 template <typename Q, typename Func>
189 bool erase( Q const& key, Func f )
191 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
192 if ( it == m_List.end() || key_comparator()( key, it->first ) != 0 )
196 cds::unref( f )( *it );
202 template <typename Q, typename Less, typename Func>
203 bool erase( Q const& key, Less pred, Func f )
205 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, pred );
206 if ( it == m_List.end() || pred( key, it->first ) || pred(it->first, key) )
210 cds::unref( f )( *it );
216 template <typename Q, typename Func>
217 bool find( Q& val, Func f )
219 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, find_predicate() );
220 if ( it == m_List.end() || key_comparator()( val, it->first ) != 0 )
224 cds::unref( f )( *it, val );
228 template <typename Q, typename Less, typename Func>
229 bool find( Q& val, Less pred, Func f )
231 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, pred );
232 if ( it == m_List.end() || pred( val, it->first ) || pred( it->first, val ) )
236 cds::unref( f )( *it, val );
240 /// Clears the container
246 iterator begin() { return m_List.begin(); }
247 const_iterator begin() const { return m_List.begin(); }
248 iterator end() { return m_List.end(); }
249 const_iterator end() const { return m_List.end(); }
251 void move_item( adapted_container& /*from*/, iterator itWhat )
253 iterator it = std::lower_bound( m_List.begin(), m_List.end(), *itWhat, find_predicate() );
254 assert( it == m_List.end() || key_comparator()( itWhat->first, it->first ) != 0 );
256 copy_item()( m_List, it, itWhat );
261 return m_List.size();
266 typedef adapted_container type ; ///< Result of \p adapt metafunction
270 }}} // namespace cds::intrusive::striped_set
273 #endif // #ifndef __CDS_CONTAINER_STRIPED_MAP_BOOST_LIST_ADAPTER_H