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