3 #ifndef __CDS_CONTAINER_STRIPED_SET_BOOST_STABLE_VECTOR_ADAPTER_H
4 #define __CDS_CONTAINER_STRIPED_SET_BOOST_STABLE_VECTOR_ADAPTER_H
6 #include <boost/version.hpp>
7 #if BOOST_VERSION < 104800
8 # error "For boost::container::stable_vector you must use boost 1.48 or above"
11 #include <functional> // ref
12 #include <algorithm> // std::lower_bound
13 #include <utility> // std::pair
14 #include <cds/container/striped_set/adapter.h>
15 #include <boost/container/stable_vector.hpp>
18 namespace cds { namespace container {
19 namespace striped_set {
21 // Copy policy for boost::container::stable_vector
22 template <typename T, typename Alloc>
23 struct copy_item_policy< boost::container::stable_vector< T, Alloc > >
25 typedef boost::container::stable_vector< T, Alloc > vector_type;
26 typedef typename vector_type::iterator iterator;
28 void operator()( vector_type& vec, iterator itInsert, iterator itWhat )
30 vec.insert( itInsert, *itWhat );
34 // Swap policy for boost::container::stable_vector
35 template <typename T, typename Alloc>
36 struct swap_item_policy< boost::container::stable_vector< T, Alloc > >
38 typedef boost::container::stable_vector< T, Alloc > vector_type;
39 typedef typename vector_type::iterator iterator;
41 void operator()( vector_type& vec, iterator itInsert, iterator itWhat )
43 typename vector_type::value_type newVal;
44 itInsert = vec.insert( itInsert, newVal );
45 std::swap( *itInsert, *itWhat );
49 // Move policy for boost::container::stable_vector
50 template <typename T, typename Alloc>
51 struct move_item_policy< boost::container::stable_vector< T, Alloc > >
53 typedef boost::container::stable_vector< T, Alloc > vector_type;
54 typedef typename vector_type::iterator iterator;
56 void operator()( vector_type& vec, iterator itInsert, iterator itWhat )
58 vec.insert( itInsert, std::move( *itWhat ));
62 } // namespace striped_set
63 }} // namespace cds::container
65 namespace cds { namespace intrusive { namespace striped_set {
66 /// boost::container::stable_vector adapter for hash set bucket
67 template <typename T, class Alloc, typename... Options>
68 class adapt< boost::container::stable_vector<T, Alloc>, Options... >
71 typedef boost::container::stable_vector<T, Alloc> container_type ; ///< underlying container type
74 /// Adapted container type
75 class adapted_container: public cds::container::striped_set::adapted_sequential_container
78 typedef typename container_type::value_type value_type ; ///< value type stored in the container
79 typedef typename container_type::iterator iterator ; ///< container iterator
80 typedef typename container_type::const_iterator const_iterator ; ///< container const iterator
82 static bool const has_find_with = true;
83 static bool const has_erase_with = true;
87 typedef typename cds::opt::details::make_comparator_from_option_list< value_type, Options... >::type key_comparator;
89 typedef typename cds::opt::select<
90 typename cds::opt::value<
91 typename cds::opt::find_option<
92 cds::opt::copy_policy< cds::container::striped_set::move_item >
96 , cds::container::striped_set::copy_item, cds::container::striped_set::copy_item_policy<container_type>
97 , cds::container::striped_set::swap_item, cds::container::striped_set::swap_item_policy<container_type>
98 , cds::container::striped_set::move_item, cds::container::striped_set::move_item_policy<container_type>
101 struct find_predicate
103 bool operator()( value_type const& i1, value_type const& i2) const
105 return key_comparator()( i1, i2 ) < 0;
108 template <typename Q>
109 bool operator()( Q const& i1, value_type const& i2) const
111 return key_comparator()( i1, i2 ) < 0;
114 template <typename Q>
115 bool operator()( value_type const& i1, Q const& i2) const
117 return key_comparator()( i1, i2 ) < 0;
124 container_type m_Vector;
129 /// Insert value \p val of type \p Q into the container
131 The function allows to split creating of new item into two part:
132 - create item with key only from \p val
133 - try to insert new item into the container
134 - if inserting is success, calls \p f functor to initialize value-field of the new item.
136 The functor signature is:
138 void func( value_type& item );
140 where \p item is the item inserted.
142 The type \p Q may differ from \ref value_type of items storing in the container.
143 Therefore, the \p value_type should be comparable with type \p Q and constructible from type \p Q,
145 The user-defined functor is called only if the inserting is success.
147 template <typename Q, typename Func>
148 bool insert( const Q& val, Func f )
150 iterator it = std::lower_bound( m_Vector.begin(), m_Vector.end(), val, find_predicate() );
151 if ( it == m_Vector.end() || key_comparator()( val, *it ) != 0 ) {
152 value_type newItem( val );
153 it = m_Vector.insert( it, newItem );
160 template <typename... Args>
161 bool emplace( Args&&... args )
163 value_type val( std::forward<Args>(args)... );
164 iterator it = std::lower_bound( m_Vector.begin(), m_Vector.end(), val, find_predicate() );
165 if ( it == m_Vector.end() || key_comparator()( val, *it ) != 0 ) {
166 it = m_Vector.emplace( it, std::move( val ) );
172 /// Ensures that the \p item exists in the container
174 The operation performs inserting or changing data.
176 If the \p val key not found in the container, then the new item created from \p val
177 is inserted. Otherwise, the functor \p func is called with the item found.
178 The \p Func functor has interface:
180 void func( bool bNew, value_type& item, const Q& val );
185 void operator()( bool bNew, value_type& item, const Q& val );
190 - \p bNew - \p true if the item has been inserted, \p false otherwise
191 - \p item - container's item
192 - \p val - argument \p val passed into the \p ensure function
194 The functor may change non-key fields of the \p item.
196 The type \p Q may differ from \ref value_type of items storing in the container.
197 Therefore, the \p value_type should be comparable with type \p Q and constructible from type \p Q,
199 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
200 \p second is true if new item has been added or \p false if the item with \p val key
203 template <typename Q, typename Func>
204 std::pair<bool, bool> ensure( const Q& val, Func func )
206 iterator it = std::lower_bound( m_Vector.begin(), m_Vector.end(), val, find_predicate() );
207 if ( it == m_Vector.end() || key_comparator()( val, *it ) != 0 ) {
209 value_type newItem( val );
210 it = m_Vector.insert( it, newItem );
211 func( true, *it, val );
212 return std::make_pair( true, true );
216 func( false, *it, val );
217 return std::make_pair( true, false );
223 The function searches an item with key \p key, calls \p f functor
224 and deletes the item. If \p key is not found, the functor is not called.
226 The functor \p Func interface is:
229 void operator()(value_type const& val);
233 The type \p Q may differ from \ref value_type of items storing in the container.
234 Therefore, the \p value_type should be comparable with type \p Q.
236 Return \p true if key is found and deleted, \p false otherwise
238 template <typename Q, typename Func>
239 bool erase( const Q& key, Func f )
241 iterator it = std::lower_bound( m_Vector.begin(), m_Vector.end(), key, find_predicate() );
242 if ( it == m_Vector.end() || key_comparator()( key, *it ) != 0 )
247 m_Vector.erase( it );
251 template <typename Q, typename Less, typename Func>
252 bool erase( const Q& key, Less pred, Func f )
254 iterator it = std::lower_bound( m_Vector.begin(), m_Vector.end(), key, pred );
255 if ( it == m_Vector.end() || pred( key, *it ) || pred( *it, key ) )
260 m_Vector.erase( it );
264 /// Find the key \p val
266 The function searches the item with key equal to \p val and calls the functor \p f for item found.
267 The interface of \p Func functor is:
270 void operator()( value_type& item, Q& val );
273 where \p item is the item found, \p val is the <tt>find</tt> function argument.
275 The functor may change non-key fields of \p item.
276 The \p val argument is non-const since it can be used as \p f functor destination i.e., the functor
277 may modify both arguments.
279 The type \p Q may differ from \ref value_type of items storing in the container.
280 Therefore, the \p value_type should be comparable with type \p Q.
282 The function returns \p true if \p val is found, \p false otherwise.
284 template <typename Q, typename Func>
285 bool find( Q& val, Func f )
287 iterator it = std::lower_bound( m_Vector.begin(), m_Vector.end(), val, find_predicate() );
288 if ( it == m_Vector.end() || key_comparator()( val, *it ) != 0 )
296 template <typename Q, typename Less, typename Func>
297 bool find( Q& val, Less pred, Func f )
299 iterator it = std::lower_bound( m_Vector.begin(), m_Vector.end(), val, pred );
300 if ( it == m_Vector.end() || pred( val, *it ) || pred( *it, val ) )
308 /// Clears the container
314 iterator begin() { return m_Vector.begin(); }
315 const_iterator begin() const { return m_Vector.begin(); }
316 iterator end() { return m_Vector.end(); }
317 const_iterator end() const { return m_Vector.end(); }
319 void move_item( adapted_container& /*from*/, iterator itWhat )
321 iterator it = std::lower_bound( m_Vector.begin(), m_Vector.end(), *itWhat, find_predicate() );
322 assert( it == m_Vector.end() || key_comparator()( *itWhat, *it ) != 0 );
324 copy_item()( m_Vector, it, itWhat );
329 return m_Vector.size();
334 typedef adapted_container type ; ///< Result of \p adapt metafunction
337 }}} // namespace cds::intrusive::striped_set
342 #endif // #ifndef __CDS_CONTAINER_STRIPED_SET_BOOST_STABLE_VECTOR_ADAPTER_H