3 #ifndef __CDS_CONTAINER_STRIPED_SET_ADAPTER_H
4 #define __CDS_CONTAINER_STRIPED_SET_ADAPTER_H
6 #include <cds/intrusive/striped_set/adapter.h>
7 #include <cds/intrusive/striped_set/striping_policy.h>
9 namespace cds { namespace container {
10 /// Striped hash set related definitions
11 namespace striped_set {
14 struct copy_item ; // copy_item_policy tag
15 template <typename Container>
16 struct copy_item_policy;
18 struct swap_item ; // swap_item_policy tag
19 template <typename Container>
20 struct swap_item_policy;
22 struct move_item ; // move_item_policy tag
23 template <typename Container>
24 struct move_item_policy;
27 #ifdef CDS_DOXYGEN_INVOKED
28 /// Default adapter for hash set
30 By default, the metafunction does not make any transformation for container type \p Container.
31 \p Container should provide interface suitable for the hash set.
33 The \p Options template argument contains a list of options
34 that has been passed to cds::container::StripedSet.
36 <b>Bucket interface</b>
38 The result of metafunction is a container (a bucket) that should support the following interface:
40 Public typedefs that the bucket should provide:
41 - \p value_type - the type of the item in the bucket
42 - \p iterator - bucket's item iterator
43 - \p const_iterator - bucket's item constant iterator
44 - \p default_resizing_policy - defalt resizing policy preferable for the container.
45 By default, the library defines striped_set::load_factor_resizing<4> for sequential containers like
46 std::list, std::vector, and striped_set::no_resizing for ordered container like std::set,
49 <b>Insert value \p val of type \p Q</b>
50 \code template <typename Q, typename Func> bool insert( const Q& val, Func f ) ; \endcode
51 The function allows to split creating of new item into two part:
52 - create item with key only from \p val
53 - try to insert new item into the container
54 - if inserting is success, calls \p f functor to initialize value-field of the new item.
56 The functor signature is:
58 void func( value_type& item );
60 where \p item is the item inserted.
62 The type \p Q can differ from \ref value_type of items storing in the container.
63 Therefore, the \p value_type should be comparable with type \p Q and constructible from type \p Q,
65 The user-defined functor is called only if the inserting is success. It can be passed by reference
66 using <tt>boost::ref</tt>
69 <b>Inserts data of type \ref value_type constructed with <tt>std::forward<Args>(args)...</tt></b>
70 \code template <typename... Args> bool emplace( Args&&... args ) ; \endcode
71 Returns \p true if inserting successful, \p false otherwise.
73 This function should be available only for compiler that supports
74 variadic template and move semantics
77 <b>Ensures that the \p item exists in the container</b>
78 \code template <typename Q, typename Func> std::pair<bool, bool> ensure( const Q& val, Func func ) \endcode
79 The operation performs inserting or changing data.
81 If the \p val key not found in the container, then the new item created from \p val
82 is inserted. Otherwise, the functor \p func is called with the item found.
83 The \p Func functor has interface:
85 void func( bool bNew, value_type& item, const Q& val );
90 void operator()( bool bNew, value_type& item, const Q& val );
95 - \p bNew - \p true if the item has been inserted, \p false otherwise
96 - \p item - container's item
97 - \p val - argument \p val passed into the \p ensure function
99 The functor can change non-key fields of the \p item.
101 The type \p Q can differ from \ref value_type of items storing in the container.
102 Therefore, the \p value_type should be comparable with type \p Q and constructible from type \p Q,
104 You can pass \p func argument by reference using <tt>boost::ref</tt>.
106 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
107 \p second is true if new item has been added or \p false if the item with \p val key
113 \code template <typename Q, typename Func> bool erase( const Q& key, Func f ) \endcode
114 The function searches an item with key \p key, calls \p f functor
115 and deletes the item. If \p key is not found, the functor is not called.
117 The functor \p Func interface is:
120 void operator()(value_type const& val);
123 The functor can be passed by reference using <tt>boost:ref</tt>
125 The type \p Q can differ from \ref value_type of items storing in the container.
126 Therefore, the \p value_type should be comparable with type \p Q.
128 Return \p true if key is found and deleted, \p false otherwise
132 <b>Find the key \p val </b>
133 \code template <typename Q, typename Func> bool find( Q& val, Func f ) \endcode
134 The function searches the item with key equal to \p val and calls the functor \p f for item found.
135 The interface of \p Func functor is:
138 void operator()( value_type& item, Q& val );
141 where \p item is the item found, \p val is the <tt>find</tt> function argument.
143 You can pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
145 The functor can change non-key fields of \p item.
146 The \p val argument is non-const since it can be used as \p f functor destination i.e., the functor
147 can modify both arguments.
149 The type \p Q can differ from \ref value_type of items storing in the container.
150 Therefore, the \p value_type should be comparable with type \p Q.
152 The function returns \p true if \p val is found, \p false otherwise.
155 <b>Clears the container</b>
156 \code void clear() \endcode
159 <b>Get size of bucket</b>
160 \code size_t size() const \endcode
161 This function can be required by some resizing policy
164 <b>Move item when resizing</b>
165 \code void move_item( adapted_container& from, iterator it ) \endcode
166 This helper function is invented for the set resizing when the item
167 pointed by \p it iterator is copied from an old bucket \p from to a new bucket
172 template < typename Container, CDS_DECL_OPTIONS >
176 typedef Container type ; ///< adapted container type
177 typedef typename type::value_type value_type ; ///< value type stored in the container
179 #else // CDS_DOXYGEN_INVOKED
180 using cds::intrusive::striped_set::adapt;
184 using cds::intrusive::striped_set::adapted_sequential_container;
185 using cds::intrusive::striped_set::adapted_container;
187 using cds::intrusive::striped_set::load_factor_resizing;
188 using cds::intrusive::striped_set::single_bucket_size_threshold;
189 using cds::intrusive::striped_set::no_resizing;
191 using cds::intrusive::striped_set::striping;
192 using cds::intrusive::striped_set::refinable;
199 struct boost_set_copy_policies
201 struct copy_item_policy
203 typedef Set set_type;
204 typedef typename set_type::iterator iterator;
206 void operator()( set_type& set, iterator itWhat )
208 set.insert( *itWhat );
212 typedef copy_item_policy swap_item_policy;
214 struct move_item_policy
216 typedef Set set_type;
217 typedef typename set_type::iterator iterator;
219 void operator()( set_type& set, iterator itWhat )
221 set.insert( std::move( *itWhat ) );
226 template <class Set, CDS_SPEC_OPTIONS>
227 class boost_set_adapter: public striped_set::adapted_container
230 typedef Set container_type;
232 typedef typename container_type::value_type value_type ; ///< value type stored in the container
233 typedef typename container_type::iterator iterator ; ///< container iterator
234 typedef typename container_type::const_iterator const_iterator ; ///< container const iterator
236 static bool const has_find_with = false;
237 static bool const has_erase_with = false;
240 typedef typename cds::opt::select<
241 typename cds::opt::value<
242 typename cds::opt::find_option<
243 cds::opt::copy_policy< cds::container::striped_set::move_item >
247 , cds::container::striped_set::copy_item, copy_item_policy<container_type>
248 , cds::container::striped_set::swap_item, swap_item_policy<container_type>
249 , cds::container::striped_set::move_item, move_item_policy<container_type>
253 container_type m_Set;
259 container_type& base_container()
264 template <typename Q, typename Func>
265 bool insert( const Q& val, Func f )
267 std::pair<iterator, bool> res = m_Set.insert( value_type(val) );
269 cds::unref(f)( const_cast<value_type&>(*res.first) );
273 # ifdef CDS_EMPLACE_SUPPORT
274 template <typename... Args>
275 bool emplace( Args&&... args )
277 std::pair<iterator, bool> res = m_Set.emplace( std::forward<Args>(args)... );
282 template <typename Q, typename Func>
283 std::pair<bool, bool> ensure( const Q& val, Func func )
285 std::pair<iterator, bool> res = m_Set.insert( value_type(val) );
286 cds::unref(func)( res.second, const_cast<value_type&>(*res.first), val );
287 return std::make_pair( true, res.second );
290 template <typename Q, typename Func>
291 bool erase( const Q& key, Func f )
293 const_iterator it = m_Set.find( value_type(key) );
294 if ( it == m_Set.end() )
296 cds::unref(f)( const_cast<value_type&>(*it) );
301 template <typename Q, typename Func>
302 bool find( Q& val, Func f )
304 iterator it = m_Set.find( value_type(val) );
305 if ( it == m_Set.end() )
307 cds::unref(f)( const_cast<value_type&>(*it), val );
316 iterator begin() { return m_Set.begin(); }
317 const_iterator begin() const { return m_Set.begin(); }
318 iterator end() { return m_Set.end(); }
319 const_iterator end() const { return m_Set.end(); }
321 void move_item( adapted_container& /*from*/, iterator itWhat )
323 assert( m_Set.find( *itWhat ) == m_Set.end() );
324 copy_item()( m_Set, itWhat );
334 struct boost_map_copy_policies {
335 struct copy_item_policy {
336 typedef Map map_type;
337 typedef typename map_type::value_type pair_type;
338 typedef typename map_type::iterator iterator;
340 void operator()( map_type& map, iterator itWhat )
342 map.insert( *itWhat );
346 struct swap_item_policy {
347 typedef Map map_type;
348 typedef typename map_type::value_type pair_type;
349 typedef typename map_type::iterator iterator;
351 void operator()( map_type& map, iterator itWhat )
353 std::pair< iterator, bool > ret = map.insert( pair_type( itWhat->first, typename pair_type::second_type() ));
354 assert( ret.second ) ; // successful insertion
355 std::swap( ret.first->second, itWhat->second );
359 struct move_item_policy {
360 typedef Map map_type;
361 typedef typename map_type::value_type pair_type;
362 typedef typename map_type::iterator iterator;
364 void operator()( map_type& map, iterator itWhat )
366 map.insert( std::move( *itWhat ) );
371 template <class Map, CDS_SPEC_OPTIONS>
372 class boost_map_adapter: public striped_set::adapted_container
375 typedef Map container_type;
377 typedef typename container_type::value_type value_type ; ///< value type stored in the container
378 typedef typename container_type::key_type key_type;
379 typedef typename container_type::mapped_type mapped_type;
380 typedef typename container_type::iterator iterator ; ///< container iterator
381 typedef typename container_type::const_iterator const_iterator ; ///< container const iterator
383 static bool const has_find_with = false;
384 static bool const has_erase_with = false;
387 typedef typename cds::opt::select<
388 typename cds::opt::value<
389 typename cds::opt::find_option<
390 cds::opt::copy_policy< cds::container::striped_set::move_item >
394 , cds::container::striped_set::copy_item, copy_item_policy<container_type>
395 , cds::container::striped_set::swap_item, swap_item_policy<container_type>
396 , cds::container::striped_set::move_item, move_item_policy<container_type>
400 container_type m_Map;
403 template <typename Q, typename Func>
404 bool insert( const Q& key, Func f )
406 std::pair<iterator, bool> res = m_Map.insert( value_type( key, mapped_type() ) );
408 cds::unref(f)( *res.first );
412 # ifdef CDS_EMPLACE_SUPPORT
413 template <typename Q, typename... Args>
414 bool emplace( Q&& key, Args&&... args )
416 std::pair<iterator, bool> res = m_Map.emplace( std::forward<Q>(key), std::move( mapped_type( std::forward<Args>(args)...)));
421 template <typename Q, typename Func>
422 std::pair<bool, bool> ensure( const Q& val, Func func )
424 std::pair<iterator, bool> res = m_Map.insert( value_type( val, mapped_type() ));
425 cds::unref(func)( res.second, *res.first );
426 return std::make_pair( true, res.second );
429 template <typename Q, typename Func>
430 bool erase( const Q& key, Func f )
432 iterator it = m_Map.find( key_type(key) );
433 if ( it == m_Map.end() )
435 cds::unref(f)( *it );
440 template <typename Q, typename Func>
441 bool find( Q& val, Func f )
443 iterator it = m_Map.find( key_type(val) );
444 if ( it == m_Map.end() )
446 cds::unref(f)( *it, val );
455 iterator begin() { return m_Map.begin(); }
456 const_iterator begin() const { return m_Map.begin(); }
457 iterator end() { return m_Map.end(); }
458 const_iterator end() const { return m_Map.end(); }
460 void move_item( adapted_container& /*from*/, iterator itWhat )
462 assert( m_Map.find( itWhat->first ) == m_Map.end() );
463 copy_item()( m_Map, itWhat );
472 } // namespace details
475 } // namespace striped_set
476 }} // namespace cds::container
479 #endif // #ifndef __CDS_CONTAINER_STRIPED_SET_ADAPTER_H