3 #ifndef CDSLIB_CONTAINER_STRIPED_SET_ADAPTER_H
4 #define CDSLIB_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 {
12 using cds::intrusive::striped_set::implementation_tag;
15 struct copy_item ; // copy_item_policy tag
16 template <typename Container>
17 struct copy_item_policy;
19 struct swap_item ; // swap_item_policy tag
20 template <typename Container>
21 struct swap_item_policy;
23 struct move_item ; // move_item_policy tag
24 template <typename Container>
25 struct move_item_policy;
28 #ifdef CDS_DOXYGEN_INVOKED
29 /// Default adapter for hash set
31 By default, the metafunction does not make any transformation for container type \p Container.
32 \p Container should provide interface suitable for the hash set.
34 The \p Options template argument contains a list of options
35 that has been passed to cds::container::StripedSet.
37 <b>Bucket interface</b>
39 The result of metafunction is a container (a bucket) that should support the following interface:
41 Public typedefs that the bucket should provide:
42 - \p value_type - the type of the item in the bucket
43 - \p iterator - bucket's item iterator
44 - \p const_iterator - bucket's item constant iterator
45 - \p default_resizing_policy - defalt resizing policy preferable for the container.
46 By default, the library defines striped_set::load_factor_resizing<4> for sequential containers like
47 std::list, std::vector, and striped_set::no_resizing for ordered container like std::set,
50 <b>Insert value \p val of type \p Q</b>
51 \code template <typename Q, typename Func> bool insert( const Q& val, Func f ) ; \endcode
52 The function allows to split creating of new item into two part:
53 - create item with key only from \p val
54 - try to insert new item into the container
55 - if inserting is success, calls \p f functor to initialize value-field of the new item.
57 The functor signature is:
59 void func( value_type& item );
61 where \p item is the item inserted.
63 The type \p Q can differ from \ref value_type of items storing in the container.
64 Therefore, the \p value_type should be comparable with type \p Q and constructible from type \p Q,
66 The user-defined functor is called only if the inserting is success.
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 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
105 \p second is true if new item has been added or \p false if the item with \p val key
111 \code template <typename Q, typename Func> bool erase( const Q& key, Func f ) \endcode
112 The function searches an item with key \p key, calls \p f functor
113 and deletes the item. If \p key is not found, the functor is not called.
115 The functor \p Func interface is:
118 void operator()(value_type const& val);
122 The type \p Q can differ from \ref value_type of items storing in the container.
123 Therefore, the \p value_type should be comparable with type \p Q.
125 Return \p true if key is found and deleted, \p false otherwise
129 <b>Find the key \p val </b>
130 \code template <typename Q, typename Func> bool find( Q& val, Func f ) \endcode
131 The function searches the item with key equal to \p val and calls the functor \p f for item found.
132 The interface of \p Func functor is:
135 void operator()( value_type& item, Q& val );
138 where \p item is the item found, \p val is the <tt>find</tt> function argument.
140 The functor can change non-key fields of \p item.
141 The \p val argument is non-const since it can be used as \p f functor destination i.e., the functor
142 can modify both arguments.
144 The type \p Q can differ from \ref value_type of items storing in the container.
145 Therefore, the \p value_type should be comparable with type \p Q.
147 The function returns \p true if \p val is found, \p false otherwise.
150 <b>Clears the container</b>
151 \code void clear() \endcode
154 <b>Get size of bucket</b>
155 \code size_t size() const \endcode
156 This function can be required by some resizing policy
159 <b>Move item when resizing</b>
160 \code void move_item( adapted_container& from, iterator it ) \endcode
161 This helper function is invented for the set resizing when the item
162 pointed by \p it iterator is copied from an old bucket \p from to a new bucket
167 template < typename Container, typename... Options>
171 typedef Container type ; ///< adapted container type
172 typedef typename type::value_type value_type ; ///< value type stored in the container
174 #else // CDS_DOXYGEN_INVOKED
175 using cds::intrusive::striped_set::adapt;
179 using cds::intrusive::striped_set::adapted_sequential_container;
180 using cds::intrusive::striped_set::adapted_container;
182 using cds::intrusive::striped_set::load_factor_resizing;
183 using cds::intrusive::striped_set::rational_load_factor_resizing;
184 using cds::intrusive::striped_set::single_bucket_size_threshold;
185 using cds::intrusive::striped_set::no_resizing;
187 using cds::intrusive::striped_set::striping;
188 using cds::intrusive::striped_set::refinable;
195 struct boost_set_copy_policies
197 struct copy_item_policy
199 typedef Set set_type;
200 typedef typename set_type::iterator iterator;
202 void operator()( set_type& set, iterator itWhat )
204 set.insert( *itWhat );
208 typedef copy_item_policy swap_item_policy;
210 struct move_item_policy
212 typedef Set set_type;
213 typedef typename set_type::iterator iterator;
215 void operator()( set_type& set, iterator itWhat )
217 set.insert( std::move( *itWhat ) );
222 template <class Set, typename... Options>
223 class boost_set_adapter: public striped_set::adapted_container
226 typedef Set container_type;
228 typedef typename container_type::value_type value_type ; ///< value type stored in the container
229 typedef typename container_type::iterator iterator ; ///< container iterator
230 typedef typename container_type::const_iterator const_iterator ; ///< container const iterator
232 static bool const has_find_with = false;
233 static bool const has_erase_with = false;
236 typedef typename cds::opt::select<
237 typename cds::opt::value<
238 typename cds::opt::find_option<
239 cds::opt::copy_policy< cds::container::striped_set::move_item >
243 , cds::container::striped_set::copy_item, copy_item_policy<container_type>
244 , cds::container::striped_set::swap_item, swap_item_policy<container_type>
245 , cds::container::striped_set::move_item, move_item_policy<container_type>
249 container_type m_Set;
255 container_type& base_container()
260 template <typename Q, typename Func>
261 bool insert( const Q& val, Func f )
263 std::pair<iterator, bool> res = m_Set.insert( value_type(val) );
265 f( const_cast<value_type&>(*res.first) );
269 template <typename... Args>
270 bool emplace( Args&&... args )
272 std::pair<iterator, bool> res = m_Set.emplace( std::forward<Args>(args)... );
276 template <typename Q, typename Func>
277 std::pair<bool, bool> ensure( const Q& val, Func func )
279 std::pair<iterator, bool> res = m_Set.insert( value_type(val) );
280 func( res.second, const_cast<value_type&>(*res.first), val );
281 return std::make_pair( true, res.second );
284 template <typename Q, typename Func>
285 bool erase( const Q& key, Func f )
287 const_iterator it = m_Set.find( value_type(key) );
288 if ( it == m_Set.end() )
290 f( const_cast<value_type&>(*it) );
295 template <typename Q, typename Func>
296 bool find( Q& val, Func f )
298 iterator it = m_Set.find( value_type(val) );
299 if ( it == m_Set.end() )
301 f( const_cast<value_type&>(*it), val );
310 iterator begin() { return m_Set.begin(); }
311 const_iterator begin() const { return m_Set.begin(); }
312 iterator end() { return m_Set.end(); }
313 const_iterator end() const { return m_Set.end(); }
315 void move_item( adapted_container& /*from*/, iterator itWhat )
317 assert( m_Set.find( *itWhat ) == m_Set.end() );
318 copy_item()( m_Set, itWhat );
328 struct boost_map_copy_policies {
329 struct copy_item_policy {
330 typedef Map map_type;
331 typedef typename map_type::value_type pair_type;
332 typedef typename map_type::iterator iterator;
334 void operator()( map_type& map, iterator itWhat )
336 map.insert( *itWhat );
340 struct swap_item_policy {
341 typedef Map map_type;
342 typedef typename map_type::value_type pair_type;
343 typedef typename map_type::iterator iterator;
345 void operator()( map_type& map, iterator itWhat )
347 std::pair< iterator, bool > ret = map.insert( pair_type( itWhat->first, typename pair_type::second_type() ));
348 assert( ret.second ) ; // successful insertion
349 std::swap( ret.first->second, itWhat->second );
353 struct move_item_policy {
354 typedef Map map_type;
355 typedef typename map_type::value_type pair_type;
356 typedef typename map_type::iterator iterator;
358 void operator()( map_type& map, iterator itWhat )
360 map.insert( std::move( *itWhat ) );
365 template <class Map, typename... Options>
366 class boost_map_adapter: public striped_set::adapted_container
369 typedef Map container_type;
371 typedef typename container_type::value_type value_type ; ///< value type stored in the container
372 typedef typename container_type::key_type key_type;
373 typedef typename container_type::mapped_type mapped_type;
374 typedef typename container_type::iterator iterator ; ///< container iterator
375 typedef typename container_type::const_iterator const_iterator ; ///< container const iterator
377 static bool const has_find_with = false;
378 static bool const has_erase_with = false;
381 typedef typename cds::opt::select<
382 typename cds::opt::value<
383 typename cds::opt::find_option<
384 cds::opt::copy_policy< cds::container::striped_set::move_item >
388 , cds::container::striped_set::copy_item, copy_item_policy<container_type>
389 , cds::container::striped_set::swap_item, swap_item_policy<container_type>
390 , cds::container::striped_set::move_item, move_item_policy<container_type>
394 container_type m_Map;
397 template <typename Q, typename Func>
398 bool insert( const Q& key, Func f )
400 std::pair<iterator, bool> res = m_Map.insert( value_type( key, mapped_type() ) );
406 template <typename Q, typename... Args>
407 bool emplace( Q&& key, Args&&... args )
409 std::pair<iterator, bool> res = m_Map.emplace( std::forward<Q>(key), std::move( mapped_type( std::forward<Args>(args)...)));
413 template <typename Q, typename Func>
414 std::pair<bool, bool> ensure( const Q& val, Func func )
416 std::pair<iterator, bool> res = m_Map.insert( value_type( val, mapped_type() ));
417 func( res.second, *res.first );
418 return std::make_pair( true, res.second );
421 template <typename Q, typename Func>
422 bool erase( const Q& key, Func f )
424 iterator it = m_Map.find( key_type(key) );
425 if ( it == m_Map.end() )
432 template <typename Q, typename Func>
433 bool find( Q& val, Func f )
435 iterator it = m_Map.find( key_type(val) );
436 if ( it == m_Map.end() )
447 iterator begin() { return m_Map.begin(); }
448 const_iterator begin() const { return m_Map.begin(); }
449 iterator end() { return m_Map.end(); }
450 const_iterator end() const { return m_Map.end(); }
452 void move_item( adapted_container& /*from*/, iterator itWhat )
454 assert( m_Map.find( itWhat->first ) == m_Map.end() );
455 copy_item()( m_Map, itWhat );
464 } // namespace details
467 } // namespace striped_set
468 }} // namespace cds::container
471 #endif // #ifndef CDSLIB_CONTAINER_STRIPED_SET_ADAPTER_H