Use std::thread rather than pthreads in AtomicHashMapTest
[folly.git] / folly / experimental / StringKeyedUnorderedSet.h
1 /*
2  * Copyright 2016 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 // Copyright 2013-present Facebook. All Rights Reserved.
17 // @author: Pavlo Kushnir (pavlo)
18
19 #pragma once
20
21 #include <initializer_list>
22 #include <memory>
23 #include <unordered_set>
24 #include <folly/Range.h>
25 #include <folly/experimental/StringKeyedCommon.h>
26
27 namespace folly {
28
29 /**
30  * Wrapper class for unordered_set<string> that can
31  * perform lookup operations with StringPiece, not only string.
32  *
33  * It uses kind of hack: string pointed by StringPiece is copied when
34  * StringPiece is inserted into set
35  */
36 template <class Hasher = StringPieceHash,
37           class Eq = std::equal_to<StringPiece>,
38           class Alloc = std::allocator<folly::StringPiece>>
39 class BasicStringKeyedUnorderedSet
40     : private std::unordered_set<StringPiece, Hasher, Eq, Alloc> {
41   using Base = std::unordered_set<StringPiece, Hasher, Eq, Alloc>;
42
43 public:
44   typedef typename Base::key_type key_type;
45   typedef typename Base::value_type value_type;
46   typedef typename Base::hasher hasher;
47   typedef typename Base::key_equal key_equal;
48   typedef typename Base::allocator_type allocator_type;
49   typedef typename Base::reference reference;
50   typedef typename Base::const_reference const_reference;
51   typedef typename Base::pointer pointer;
52   typedef typename Base::const_pointer const_pointer;
53   typedef typename Base::iterator iterator;
54   typedef typename Base::const_iterator const_iterator;
55   typedef typename Base::size_type size_type;
56   typedef typename Base::difference_type difference_type;
57
58   // Constructors in the same order as in
59   // http://cplusplus.com/reference/unordered_set/unordered_set/unordered_set/
60   explicit BasicStringKeyedUnorderedSet() {
61   }
62
63   explicit BasicStringKeyedUnorderedSet(
64     size_type n,
65     const hasher& hf = hasher(),
66     const key_equal& eql = key_equal(),
67     const allocator_type& alloc = allocator_type())
68       : Base(n, hf, eql, alloc) {
69   }
70
71   explicit BasicStringKeyedUnorderedSet(const allocator_type& alloc)
72       : Base(alloc) {
73   }
74
75   template <class InputIterator>
76   BasicStringKeyedUnorderedSet(InputIterator b, InputIterator e) {
77     for (; b != e; ++b) {
78       emplace(*b);
79     }
80   }
81
82   template <class InputIterator>
83   BasicStringKeyedUnorderedSet(
84     InputIterator b, InputIterator e,
85     size_type n,
86     const hasher& hf = hasher(),
87     const key_equal& eql = key_equal(),
88     const allocator_type& alloc = allocator_type())
89       : Base(n, hf, eql, alloc) {
90     for (; b != e; ++b) {
91       emplace(*b);
92     }
93   }
94
95   BasicStringKeyedUnorderedSet(const BasicStringKeyedUnorderedSet& rhs)
96       : BasicStringKeyedUnorderedSet(rhs, rhs.get_allocator()) {
97   }
98
99   BasicStringKeyedUnorderedSet(const BasicStringKeyedUnorderedSet& rhs,
100                                const allocator_type& a)
101       : BasicStringKeyedUnorderedSet(rhs.begin(),
102                                      rhs.end(),
103                                      rhs.bucket_count(),
104                                      rhs.hash_function(),
105                                      rhs.key_eq(),
106                                      a) {
107   }
108
109   BasicStringKeyedUnorderedSet(BasicStringKeyedUnorderedSet&& rhs) noexcept
110       : Base(std::move(rhs)) {
111     assert(rhs.empty());
112   }
113
114   BasicStringKeyedUnorderedSet(BasicStringKeyedUnorderedSet&& rhs,
115                                const allocator_type& /* a */) noexcept
116       : Base(std::move(rhs) /* , a */ /* not supported by gcc */) {
117     assert(rhs.empty());
118   }
119
120   BasicStringKeyedUnorderedSet(std::initializer_list<value_type> il)
121       : BasicStringKeyedUnorderedSet(il.begin(), il.end()) {
122   }
123
124   BasicStringKeyedUnorderedSet(
125     std::initializer_list<value_type> il,
126     size_type n,
127     const hasher& hf = hasher(),
128     const key_equal& eql = key_equal(),
129     const allocator_type& alloc = allocator_type())
130       : BasicStringKeyedUnorderedSet(il.begin(), il.end(), n, hf, eql, alloc) {
131   }
132
133   BasicStringKeyedUnorderedSet&
134   operator=(const BasicStringKeyedUnorderedSet& rhs) & {
135     if (this == &rhs) {
136       return *this;
137     }
138     // Cost is as bad as a full copy, so to it via copy + move
139     return *this = BasicStringKeyedUnorderedSet(rhs);
140   }
141
142   BasicStringKeyedUnorderedSet&
143   operator=(BasicStringKeyedUnorderedSet&& rhs) & noexcept {
144     assert(this != &rhs);
145     clear();
146     Base::operator=(std::move(rhs));
147     return *this;
148   }
149
150   using Base::empty;
151   using Base::size;
152   using Base::max_size;
153   using Base::begin;
154   using Base::end;
155   using Base::cbegin;
156   using Base::cend;
157   using Base::find;
158
159   bool operator==(const BasicStringKeyedUnorderedSet& rhs) const {
160     const Base& lhs = *this;
161     return lhs == rhs;
162   }
163
164   template <class... Args>
165   std::pair<iterator, bool> emplace(Args&&... args) {
166     auto key = StringPiece(std::forward<Args>(args)...);
167     auto it = find(key);
168     return it != end()
169       ? std::make_pair(it, false)
170       : Base::emplace(stringPieceDup(key, get_allocator()));
171   }
172
173   std::pair<iterator, bool> insert(value_type val) {
174     auto it = find(val);
175     return it != end()
176       ? std::make_pair(it, false)
177       : Base::insert(stringPieceDup(val, get_allocator()));
178   }
179
180   iterator erase(const_iterator position) {
181     auto key = *position;
182     auto result = Base::erase(position);
183     stringPieceDel(key, get_allocator());
184     return result;
185   }
186
187   size_type erase(folly::StringPiece key) {
188     auto it = find(key);
189     if (it == end()) {
190       return 0;
191     }
192     erase(it);
193     return 1;
194   }
195
196   void clear() noexcept {
197     for (auto& it : *this) {
198       stringPieceDel(it, get_allocator());
199     }
200     Base::clear();
201   }
202
203   using Base::reserve;
204   using Base::hash_function;
205   using Base::key_eq;
206   using Base::get_allocator;
207   using Base::bucket_count;
208   using Base::max_bucket_count;
209   using Base::bucket_size;
210   using Base::bucket;
211
212   ~BasicStringKeyedUnorderedSet() {
213     // Here we assume that unordered_set doesn't use keys in destructor
214     for (auto& it : *this) {
215       stringPieceDel(it, get_allocator());
216     }
217   }
218 };
219
220 typedef BasicStringKeyedUnorderedSet<> StringKeyedUnorderedSet;
221
222 } // folly