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