3 #ifndef __CDS_CONTAINER_STRIPED_SET_STD_LIST_ADAPTER_H
4 #define __CDS_CONTAINER_STRIPED_SET_STD_LIST_ADAPTER_H
6 #include <cds/container/striped_set/adapter.h>
9 #include <algorithm> // std::lower_bound
12 namespace cds { namespace container {
13 namespace striped_set {
15 // Copy policy for std::list
16 template <typename T, typename Alloc>
17 struct copy_item_policy< std::list< T, Alloc > >
19 typedef std::list< T, Alloc > list_type;
20 typedef typename list_type::iterator iterator;
22 void operator()( list_type& list, iterator itInsert, iterator itWhat )
24 itInsert = list.insert( itInsert, *itWhat );
28 // Swap policy for std::list
29 template <typename T, typename Alloc>
30 struct swap_item_policy< std::list< T, Alloc > >
32 typedef std::list< T, Alloc > list_type;
33 typedef typename list_type::iterator iterator;
35 void operator()( list_type& list, iterator itInsert, iterator itWhat )
37 typename list_type::value_type newVal;
38 itInsert = list.insert( itInsert, newVal );
39 std::swap( *itWhat, *itInsert );
43 #ifdef CDS_MOVE_SEMANTICS_SUPPORT
44 // Move policy for std::list
45 template <typename T, typename Alloc>
46 struct move_item_policy< std::list< T, Alloc > >
48 typedef std::list< T, Alloc > list_type;
49 typedef typename list_type::iterator iterator;
51 void operator()( list_type& list, iterator itInsert, iterator itWhat )
53 list.insert( itInsert, std::move( *itWhat ) );
57 } // namespace striped_set
58 }} // namespace cds::container
60 namespace cds { namespace intrusive { namespace striped_set {
62 /// std::list adapter for hash set bucket
63 template <typename T, class Alloc, CDS_SPEC_OPTIONS>
64 class adapt< std::list<T, Alloc>, CDS_OPTIONS >
67 typedef std::list<T, Alloc> container_type ; ///< underlying container type
70 /// Adapted container type
71 class adapted_container: public cds::container::striped_set::adapted_sequential_container
74 typedef typename container_type::value_type value_type ; ///< value type stored in the container
75 typedef typename container_type::iterator iterator ; ///< container iterator
76 typedef typename container_type::const_iterator const_iterator ; ///< container const iterator
78 static bool const has_find_with = true;
79 static bool const has_erase_with = true;
83 typedef typename cds::opt::details::make_comparator_from_option_list< value_type, CDS_OPTIONS >::type key_comparator;
86 typedef typename cds::opt::select<
87 typename cds::opt::value<
88 typename cds::opt::find_option<
89 cds::opt::copy_policy< cds::container::striped_set::move_item >
93 , cds::container::striped_set::copy_item, cds::container::striped_set::copy_item_policy<container_type>
94 , cds::container::striped_set::swap_item, cds::container::striped_set::swap_item_policy<container_type>
95 #ifdef CDS_MOVE_SEMANTICS_SUPPORT
96 , cds::container::striped_set::move_item, cds::container::striped_set::move_item_policy<container_type>
100 struct find_predicate
102 bool operator()( value_type const& i1, value_type const& i2) const
104 return key_comparator()( i1, i2 ) < 0;
107 template <typename Q>
108 bool operator()( Q const& i1, value_type const& i2) const
110 return key_comparator()( i1, i2 ) < 0;
113 template <typename Q>
114 bool operator()( value_type const& i1, Q const& i2) const
116 return key_comparator()( i1, i2 ) < 0;
123 container_type m_List;
126 // In GCC (at least up to 4.7.x), the complexity of std::list::size() is O(N)
127 // (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49561)
128 size_t m_nSize ; // list size
139 template <typename Q, typename Func>
140 bool insert( const Q& val, Func f )
142 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, find_predicate() );
143 if ( it == m_List.end() || key_comparator()( val, *it ) != 0 ) {
144 value_type newItem( val );
145 it = m_List.insert( it, newItem );
146 cds::unref( f )( *it );
154 // key already exists
158 # ifdef CDS_EMPLACE_SUPPORT
159 template <typename... Args>
160 bool emplace( Args&&... args )
162 #if CDS_COMPILER == CDS_COMPILER_MSVC && CDS_COMPILER_VERSION == CDS_COMPILER_MSVC12
163 // MS VC++ 2013: internal compiler error
164 // Use assignment workaround, see http://connect.microsoft.com/VisualStudio/feedback/details/804941/visual-studio-2013-rc-c-internal-compiler-error-with-std-forward
165 value_type val = value_type( std::forward<Args>(args)... );
167 value_type val(std::forward<Args>(args)...);
169 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, find_predicate() );
170 if ( it == m_List.end() || key_comparator()( val, *it ) != 0 ) {
171 it = m_List.emplace( it, std::move( val ) );
181 template <typename Q, typename Func>
182 std::pair<bool, bool> ensure( const Q& val, Func func )
184 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, find_predicate() );
185 if ( it == m_List.end() || key_comparator()( val, *it ) != 0 ) {
187 value_type newItem( val );
188 it = m_List.insert( it, newItem );
189 cds::unref( func )( true, *it, val );
193 return std::make_pair( true, true );
197 cds::unref( func )( false, *it, val );
198 return std::make_pair( true, false );
202 template <typename Q, typename Func>
203 bool erase( const Q& key, Func f )
205 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, find_predicate() );
206 if ( it == m_List.end() || key_comparator()( key, *it ) != 0 )
210 cds::unref( f )( *it );
219 template <typename Q, typename Less, typename Func>
220 bool erase( Q const& key, Less pred, Func f )
222 iterator it = std::lower_bound( m_List.begin(), m_List.end(), key, pred );
223 if ( it == m_List.end() || pred( key, *it ) || pred( *it, key ) )
227 cds::unref( f )( *it );
236 template <typename Q, typename Func>
237 bool find( Q& val, Func f )
239 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, find_predicate() );
240 if ( it == m_List.end() || key_comparator()( val, *it ) != 0 )
244 cds::unref( f )( *it, val );
248 template <typename Q, typename Less, typename Func>
249 bool find( Q& val, Less pred, Func f )
251 iterator it = std::lower_bound( m_List.begin(), m_List.end(), val, pred );
252 if ( it == m_List.end() || pred( val, *it ) || pred( *it, val ) )
256 cds::unref( f )( *it, val );
260 /// Clears the container
266 iterator begin() { return m_List.begin(); }
267 const_iterator begin() const { return m_List.begin(); }
268 iterator end() { return m_List.end(); }
269 const_iterator end() const { return m_List.end(); }
271 void move_item( adapted_container& /*from*/, iterator itWhat )
273 iterator it = std::lower_bound( m_List.begin(), m_List.end(), *itWhat, find_predicate() );
274 assert( it == m_List.end() || key_comparator()( *itWhat, *it ) != 0 );
276 copy_item()( m_List, it, itWhat );
287 return m_List.size();
294 typedef adapted_container type ; ///< Result of \p adapt metafunction
302 #endif // #ifndef __CDS_CONTAINER_STRIPED_SET_STD_LIST_ADAPTER_H