9ec936990a28e541a535fdf6ecf0ab81ca78ebc6
[libcds.git] / cds / intrusive / striped_set / boost_unordered_set.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_INTRUSIVE_STRIPED_SET_BOOST_UNORDERED_SET_ADAPTER_H
4 #define __CDS_INTRUSIVE_STRIPED_SET_BOOST_UNORDERED_SET_ADAPTER_H
5
6 #include <boost/intrusive/unordered_set.hpp>
7 #include <cds/intrusive/striped_set/adapter.h>
8 #include <cds/opt/buffer.h>
9
10 //@cond
11 namespace cds { namespace intrusive { namespace striped_set {
12
13     namespace details {
14         template <class Set, typename... Options>
15         class adapt_boost_unordered_set
16         {
17         public:
18             typedef Set container_type;   ///< underlying intrusive container type
19
20         private:
21             class adapted_container
22             {
23             public:
24                 typedef typename container_type::value_type     value_type;   ///< value type stored in the container
25                 typedef typename container_type::iterator       iterator;   ///< container iterator
26                 typedef typename container_type::const_iterator const_iterator;   ///< container const iterator
27
28                 typedef typename opt::value <
29                     typename opt::find_option <
30                     opt::buffer< opt::v::static_buffer< cds::any_type, 256 > >,
31                     Options...
32                     > ::type
33                 > ::buffer    initial_buffer_type;
34                 typedef typename initial_buffer_type::template rebind< typename container_type::bucket_type >::other    buffer_type;
35                 typedef cds::intrusive::striped_set::load_factor_resizing<256>   default_resizing_policy;
36
37             private:
38                 template <typename Compare>
39                 struct equal_from_compare
40                 {
41                     Compare& m_cmp;
42                     equal_from_compare( Compare& cmp )
43                         : m_cmp( cmp )
44                     {}
45
46                     equal_from_compare( equal_from_compare const& src )
47                         : m_cmp( src.m_cmp )
48                     {}
49
50                     template <typename A, typename B>
51                     bool operator()( A& a, B& b ) const
52                     {
53                         return !m_cmp( a, b ) && !m_cmp( b, a );
54                     }
55
56                     template <typename A, typename B>
57                     bool operator()( A& a, B& b )
58                     {
59                         return !m_cmp( a, b ) && !m_cmp( b, a );
60                     }
61                 };
62
63                 buffer_type     m_Buckets;   // buffer should be declared first since it is used in m_Set ctor.
64                 container_type  m_Set;
65
66             public:
67                 adapted_container()
68                     : m_Set( typename container_type::bucket_traits( m_Buckets.buffer(), m_Buckets.capacity() ) )
69                 {}
70
71                 container_type& base_container()
72                 {
73                     return m_Set;
74                 }
75
76                 template <typename Func>
77                 bool insert( value_type& val, Func f )
78                 {
79                     std::pair<iterator, bool> res = m_Set.insert( val );
80                     if ( res.second )
81                         f( val );
82                     return res.second;
83                 }
84
85                 template <typename Func>
86                 std::pair<bool, bool> ensure( value_type& val, Func f )
87                 {
88                     std::pair<iterator, bool> res = m_Set.insert( val );
89                     f( res.second, *res.first, val );
90                     return std::make_pair( true, res.second );
91                 }
92
93                 bool unlink( value_type& val )
94                 {
95                     iterator it = m_Set.find( value_type( val ) );
96                     if ( it == m_Set.end() || &(*it) != &val )
97                         return false;
98                     m_Set.erase( it );
99                     return true;
100                 }
101
102                 template <typename Q, typename Func>
103                 value_type * erase( Q const& key, Func f )
104                 {
105                     iterator it = m_Set.find( key, typename container_type::hasher(), typename container_type::key_equal() );
106                     if ( it == m_Set.end() )
107                         return nullptr;
108                     value_type& val = *it;
109                     f( val );
110                     m_Set.erase( it );
111                     return &val;
112                 }
113
114                 template <typename Q, typename Less, typename Func>
115                 value_type * erase( Q const& key, Less pred, Func f )
116                 {
117                     iterator it = m_Set.find( key, typename container_type::hasher(), equal_from_compare<Less>( pred ) );
118                     if ( it == m_Set.end() )
119                         return nullptr;
120                     value_type& val = *it;
121                     f( val );
122                     m_Set.erase( it );
123                     return &val;
124                 }
125
126                 template <typename Q, typename Func>
127                 bool find( Q& key, Func f )
128                 {
129                     iterator it = m_Set.find( key, typename container_type::hasher(), typename container_type::key_equal() );
130                     if ( it == m_Set.end() )
131                         return false;
132                     f( *it, key );
133                     return true;
134                 }
135
136                 template <typename Q, typename Less, typename Func>
137                 bool find( Q& key, Less pred, Func f )
138                 {
139                     iterator it = m_Set.find( key, typename container_type::hasher(), equal_from_compare<Less>( pred ) );
140                     if ( it == m_Set.end() )
141                         return false;
142                     f( *it, key );
143                     return true;
144                 }
145
146                 void clear()
147                 {
148                     m_Set.clear();
149                 }
150
151                 template <typename Disposer>
152                 void clear( Disposer disposer )
153                 {
154                     m_Set.clear_and_dispose( disposer );
155                 }
156
157                 iterator begin() { return m_Set.begin(); }
158                 const_iterator begin() const { return m_Set.begin(); }
159                 iterator end() { return m_Set.end(); }
160                 const_iterator end() const { return m_Set.end(); }
161
162                 size_t size() const
163                 {
164                     return (size_t)m_Set.size();
165                 }
166
167                 void move_item( adapted_container& from, iterator itWhat )
168                 {
169                     value_type& val = *itWhat;
170                     from.base_container().erase( itWhat );
171                     insert( val, []( value_type& ) {} );
172                 }
173             };
174
175         public:
176             typedef adapted_container   type;  ///< Result of the metafunction
177         };
178     } // namespace details
179
180 #if CDS_COMPILER == CDS_COMPILER_INTEL && CDS_COMPILER_VERSION <= 1500
181     template <typename T,
182         typename O1, typename O2, typename O3, typename O4, typename O5,
183         typename O6, typename O7, typename O8, typename O9, typename O10,
184         typename... Options
185     >
186     class adapt < boost::intrusive::unordered_set< T, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10 >, Options... >
187         : public details::adapt_boost_unordered_set < boost::intrusive::unordered_set< T, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10 >, Options... >
188     {};
189 #else
190     template <typename T, typename... BIOptons, typename... Options>
191     class adapt < boost::intrusive::unordered_set< T, BIOptons... >, Options... >
192         : public details::adapt_boost_unordered_set < boost::intrusive::unordered_set< T, BIOptons... >, Options... >
193     {};
194 #endif
195
196 }}} // namespace cds::intrusive::striped_set
197 //@endcond
198
199 #endif // #ifndef __CDS_INTRUSIVE_STRIPED_SET_BOOST_UNORDERED_SET_ADAPTER_H