raw_hash_set.h 112 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886
  1. // Copyright 2018 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //
  15. // An open-addressing
  16. // hashtable with quadratic probing.
  17. //
  18. // This is a low level hashtable on top of which different interfaces can be
  19. // implemented, like flat_hash_set, node_hash_set, string_hash_set, etc.
  20. //
  21. // The table interface is similar to that of std::unordered_set. Notable
  22. // differences are that most member functions support heterogeneous keys when
  23. // BOTH the hash and eq functions are marked as transparent. They do so by
  24. // providing a typedef called `is_transparent`.
  25. //
  26. // When heterogeneous lookup is enabled, functions that take key_type act as if
  27. // they have an overload set like:
  28. //
  29. // iterator find(const key_type& key);
  30. // template <class K>
  31. // iterator find(const K& key);
  32. //
  33. // size_type erase(const key_type& key);
  34. // template <class K>
  35. // size_type erase(const K& key);
  36. //
  37. // std::pair<iterator, iterator> equal_range(const key_type& key);
  38. // template <class K>
  39. // std::pair<iterator, iterator> equal_range(const K& key);
  40. //
  41. // When heterogeneous lookup is disabled, only the explicit `key_type` overloads
  42. // exist.
  43. //
  44. // find() also supports passing the hash explicitly:
  45. //
  46. // iterator find(const key_type& key, size_t hash);
  47. // template <class U>
  48. // iterator find(const U& key, size_t hash);
  49. //
  50. // In addition the pointer to element and iterator stability guarantees are
  51. // weaker: all iterators and pointers are invalidated after a new element is
  52. // inserted.
  53. //
  54. // IMPLEMENTATION DETAILS
  55. //
  56. // # Table Layout
  57. //
  58. // A raw_hash_set's backing array consists of control bytes followed by slots
  59. // that may or may not contain objects.
  60. //
  61. // The layout of the backing array, for `capacity` slots, is thus, as a
  62. // pseudo-struct:
  63. //
  64. // struct BackingArray {
  65. // // The number of elements we can insert before growing the capacity.
  66. // size_t growth_left;
  67. // // Control bytes for the "real" slots.
  68. // ctrl_t ctrl[capacity];
  69. // // Always `ctrl_t::kSentinel`. This is used by iterators to find when to
  70. // // stop and serves no other purpose.
  71. // ctrl_t sentinel;
  72. // // A copy of the first `kWidth - 1` elements of `ctrl`. This is used so
  73. // // that if a probe sequence picks a value near the end of `ctrl`,
  74. // // `Group` will have valid control bytes to look at.
  75. // ctrl_t clones[kWidth - 1];
  76. // // The actual slot data.
  77. // slot_type slots[capacity];
  78. // };
  79. //
  80. // The length of this array is computed by `AllocSize()` below.
  81. //
  82. // Control bytes (`ctrl_t`) are bytes (collected into groups of a
  83. // platform-specific size) that define the state of the corresponding slot in
  84. // the slot array. Group manipulation is tightly optimized to be as efficient
  85. // as possible: SSE and friends on x86, clever bit operations on other arches.
  86. //
  87. // Group 1 Group 2 Group 3
  88. // +---------------+---------------+---------------+
  89. // | | | | | | | | | | | | | | | | | | | | | | | | |
  90. // +---------------+---------------+---------------+
  91. //
  92. // Each control byte is either a special value for empty slots, deleted slots
  93. // (sometimes called *tombstones*), and a special end-of-table marker used by
  94. // iterators, or, if occupied, seven bits (H2) from the hash of the value in the
  95. // corresponding slot.
  96. //
  97. // Storing control bytes in a separate array also has beneficial cache effects,
  98. // since more logical slots will fit into a cache line.
  99. //
  100. // # Hashing
  101. //
  102. // We compute two separate hashes, `H1` and `H2`, from the hash of an object.
  103. // `H1(hash(x))` is an index into `slots`, and essentially the starting point
  104. // for the probe sequence. `H2(hash(x))` is a 7-bit value used to filter out
  105. // objects that cannot possibly be the one we are looking for.
  106. //
  107. // # Table operations.
  108. //
  109. // The key operations are `insert`, `find`, and `erase`.
  110. //
  111. // Since `insert` and `erase` are implemented in terms of `find`, we describe
  112. // `find` first. To `find` a value `x`, we compute `hash(x)`. From
  113. // `H1(hash(x))` and the capacity, we construct a `probe_seq` that visits every
  114. // group of slots in some interesting order.
  115. //
  116. // We now walk through these indices. At each index, we select the entire group
  117. // starting with that index and extract potential candidates: occupied slots
  118. // with a control byte equal to `H2(hash(x))`. If we find an empty slot in the
  119. // group, we stop and return an error. Each candidate slot `y` is compared with
  120. // `x`; if `x == y`, we are done and return `&y`; otherwise we continue to the
  121. // next probe index. Tombstones effectively behave like full slots that never
  122. // match the value we're looking for.
  123. //
  124. // The `H2` bits ensure when we compare a slot to an object with `==`, we are
  125. // likely to have actually found the object. That is, the chance is low that
  126. // `==` is called and returns `false`. Thus, when we search for an object, we
  127. // are unlikely to call `==` many times. This likelyhood can be analyzed as
  128. // follows (assuming that H2 is a random enough hash function).
  129. //
  130. // Let's assume that there are `k` "wrong" objects that must be examined in a
  131. // probe sequence. For example, when doing a `find` on an object that is in the
  132. // table, `k` is the number of objects between the start of the probe sequence
  133. // and the final found object (not including the final found object). The
  134. // expected number of objects with an H2 match is then `k/128`. Measurements
  135. // and analysis indicate that even at high load factors, `k` is less than 32,
  136. // meaning that the number of "false positive" comparisons we must perform is
  137. // less than 1/8 per `find`.
  138. // `insert` is implemented in terms of `unchecked_insert`, which inserts a
  139. // value presumed to not be in the table (violating this requirement will cause
  140. // the table to behave erratically). Given `x` and its hash `hash(x)`, to insert
  141. // it, we construct a `probe_seq` once again, and use it to find the first
  142. // group with an unoccupied (empty *or* deleted) slot. We place `x` into the
  143. // first such slot in the group and mark it as full with `x`'s H2.
  144. //
  145. // To `insert`, we compose `unchecked_insert` with `find`. We compute `h(x)` and
  146. // perform a `find` to see if it's already present; if it is, we're done. If
  147. // it's not, we may decide the table is getting overcrowded (i.e. the load
  148. // factor is greater than 7/8 for big tables; `is_small()` tables use a max load
  149. // factor of 1); in this case, we allocate a bigger array, `unchecked_insert`
  150. // each element of the table into the new array (we know that no insertion here
  151. // will insert an already-present value), and discard the old backing array. At
  152. // this point, we may `unchecked_insert` the value `x`.
  153. //
  154. // Below, `unchecked_insert` is partly implemented by `prepare_insert`, which
  155. // presents a viable, initialized slot pointee to the caller.
  156. //
  157. // `erase` is implemented in terms of `erase_at`, which takes an index to a
  158. // slot. Given an offset, we simply create a tombstone and destroy its contents.
  159. // If we can prove that the slot would not appear in a probe sequence, we can
  160. // make the slot as empty, instead. We can prove this by observing that if a
  161. // group has any empty slots, it has never been full (assuming we never create
  162. // an empty slot in a group with no empties, which this heuristic guarantees we
  163. // never do) and find would stop at this group anyways (since it does not probe
  164. // beyond groups with empties).
  165. //
  166. // `erase` is `erase_at` composed with `find`: if we
  167. // have a value `x`, we can perform a `find`, and then `erase_at` the resulting
  168. // slot.
  169. //
  170. // To iterate, we simply traverse the array, skipping empty and deleted slots
  171. // and stopping when we hit a `kSentinel`.
  172. #ifndef Y_ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
  173. #define Y_ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
  174. #include <algorithm>
  175. #include <cmath>
  176. #include <cstddef>
  177. #include <cstdint>
  178. #include <cstring>
  179. #include <iterator>
  180. #include <limits>
  181. #include <memory>
  182. #include <util/generic/string.h>
  183. #include <tuple>
  184. #include <type_traits>
  185. #include <utility>
  186. #include "y_absl/base/config.h"
  187. #include "y_absl/base/internal/endian.h"
  188. #include "y_absl/base/internal/raw_logging.h"
  189. #include "y_absl/base/optimization.h"
  190. #include "y_absl/base/port.h"
  191. #include "y_absl/base/prefetch.h"
  192. #include "y_absl/container/internal/common.h"
  193. #include "y_absl/container/internal/compressed_tuple.h"
  194. #include "y_absl/container/internal/container_memory.h"
  195. #include "y_absl/container/internal/hash_policy_traits.h"
  196. #include "y_absl/container/internal/hashtable_debug_hooks.h"
  197. #include "y_absl/container/internal/hashtablez_sampler.h"
  198. #include "y_absl/memory/memory.h"
  199. #include "y_absl/meta/type_traits.h"
  200. #include "y_absl/numeric/bits.h"
  201. #include "y_absl/utility/utility.h"
  202. #ifdef Y_ABSL_INTERNAL_HAVE_SSE2
  203. #include <emmintrin.h>
  204. #endif
  205. #ifdef Y_ABSL_INTERNAL_HAVE_SSSE3
  206. #include <tmmintrin.h>
  207. #endif
  208. #ifdef _MSC_VER
  209. #include <intrin.h>
  210. #endif
  211. #ifdef Y_ABSL_INTERNAL_HAVE_ARM_NEON
  212. #include <arm_neon.h>
  213. #endif
  214. namespace y_absl {
  215. Y_ABSL_NAMESPACE_BEGIN
  216. namespace container_internal {
  217. #ifdef Y_ABSL_SWISSTABLE_ENABLE_GENERATIONS
  218. #error Y_ABSL_SWISSTABLE_ENABLE_GENERATIONS cannot be directly set
  219. #elif defined(Y_ABSL_HAVE_ADDRESS_SANITIZER) || \
  220. defined(Y_ABSL_HAVE_MEMORY_SANITIZER)
  221. // When compiled in sanitizer mode, we add generation integers to the backing
  222. // array and iterators. In the backing array, we store the generation between
  223. // the control bytes and the slots. When iterators are dereferenced, we assert
  224. // that the container has not been mutated in a way that could cause iterator
  225. // invalidation since the iterator was initialized.
  226. #define Y_ABSL_SWISSTABLE_ENABLE_GENERATIONS
  227. #endif
  228. // We use uint8_t so we don't need to worry about padding.
  229. using GenerationType = uint8_t;
  230. // A sentinel value for empty generations. Using 0 makes it easy to constexpr
  231. // initialize an array of this value.
  232. constexpr GenerationType SentinelEmptyGeneration() { return 0; }
  233. constexpr GenerationType NextGeneration(GenerationType generation) {
  234. return ++generation == SentinelEmptyGeneration() ? ++generation : generation;
  235. }
  236. #ifdef Y_ABSL_SWISSTABLE_ENABLE_GENERATIONS
  237. constexpr bool SwisstableGenerationsEnabled() { return true; }
  238. constexpr size_t NumGenerationBytes() { return sizeof(GenerationType); }
  239. #else
  240. constexpr bool SwisstableGenerationsEnabled() { return false; }
  241. constexpr size_t NumGenerationBytes() { return 0; }
  242. #endif
  243. template <typename AllocType>
  244. void SwapAlloc(AllocType& lhs, AllocType& rhs,
  245. std::true_type /* propagate_on_container_swap */) {
  246. using std::swap;
  247. swap(lhs, rhs);
  248. }
  249. template <typename AllocType>
  250. void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/,
  251. std::false_type /* propagate_on_container_swap */) {}
  252. // The state for a probe sequence.
  253. //
  254. // Currently, the sequence is a triangular progression of the form
  255. //
  256. // p(i) := Width * (i^2 + i)/2 + hash (mod mask + 1)
  257. //
  258. // The use of `Width` ensures that each probe step does not overlap groups;
  259. // the sequence effectively outputs the addresses of *groups* (although not
  260. // necessarily aligned to any boundary). The `Group` machinery allows us
  261. // to check an entire group with minimal branching.
  262. //
  263. // Wrapping around at `mask + 1` is important, but not for the obvious reason.
  264. // As described above, the first few entries of the control byte array
  265. // are mirrored at the end of the array, which `Group` will find and use
  266. // for selecting candidates. However, when those candidates' slots are
  267. // actually inspected, there are no corresponding slots for the cloned bytes,
  268. // so we need to make sure we've treated those offsets as "wrapping around".
  269. //
  270. // It turns out that this probe sequence visits every group exactly once if the
  271. // number of groups is a power of two, since (i^2+i)/2 is a bijection in
  272. // Z/(2^m). See https://en.wikipedia.org/wiki/Quadratic_probing
  273. template <size_t Width>
  274. class probe_seq {
  275. public:
  276. // Creates a new probe sequence using `hash` as the initial value of the
  277. // sequence and `mask` (usually the capacity of the table) as the mask to
  278. // apply to each value in the progression.
  279. probe_seq(size_t hash, size_t mask) {
  280. assert(((mask + 1) & mask) == 0 && "not a mask");
  281. mask_ = mask;
  282. offset_ = hash & mask_;
  283. }
  284. // The offset within the table, i.e., the value `p(i)` above.
  285. size_t offset() const { return offset_; }
  286. size_t offset(size_t i) const { return (offset_ + i) & mask_; }
  287. void next() {
  288. index_ += Width;
  289. offset_ += index_;
  290. offset_ &= mask_;
  291. }
  292. // 0-based probe index, a multiple of `Width`.
  293. size_t index() const { return index_; }
  294. private:
  295. size_t mask_;
  296. size_t offset_;
  297. size_t index_ = 0;
  298. };
  299. template <class ContainerKey, class Hash, class Eq>
  300. struct RequireUsableKey {
  301. template <class PassedKey, class... Args>
  302. std::pair<
  303. decltype(std::declval<const Hash&>()(std::declval<const PassedKey&>())),
  304. decltype(std::declval<const Eq&>()(std::declval<const ContainerKey&>(),
  305. std::declval<const PassedKey&>()))>*
  306. operator()(const PassedKey&, const Args&...) const;
  307. };
  308. template <class E, class Policy, class Hash, class Eq, class... Ts>
  309. struct IsDecomposable : std::false_type {};
  310. template <class Policy, class Hash, class Eq, class... Ts>
  311. struct IsDecomposable<
  312. y_absl::void_t<decltype(Policy::apply(
  313. RequireUsableKey<typename Policy::key_type, Hash, Eq>(),
  314. std::declval<Ts>()...))>,
  315. Policy, Hash, Eq, Ts...> : std::true_type {};
  316. // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
  317. template <class T>
  318. constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
  319. using std::swap;
  320. return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
  321. }
  322. template <class T>
  323. constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
  324. return false;
  325. }
  326. template <typename T>
  327. uint32_t TrailingZeros(T x) {
  328. Y_ABSL_ASSUME(x != 0);
  329. return static_cast<uint32_t>(countr_zero(x));
  330. }
  331. // An abstract bitmask, such as that emitted by a SIMD instruction.
  332. //
  333. // Specifically, this type implements a simple bitset whose representation is
  334. // controlled by `SignificantBits` and `Shift`. `SignificantBits` is the number
  335. // of abstract bits in the bitset, while `Shift` is the log-base-two of the
  336. // width of an abstract bit in the representation.
  337. // This mask provides operations for any number of real bits set in an abstract
  338. // bit. To add iteration on top of that, implementation must guarantee no more
  339. // than one real bit is set in an abstract bit.
  340. template <class T, int SignificantBits, int Shift = 0>
  341. class NonIterableBitMask {
  342. public:
  343. explicit NonIterableBitMask(T mask) : mask_(mask) {}
  344. explicit operator bool() const { return this->mask_ != 0; }
  345. // Returns the index of the lowest *abstract* bit set in `self`.
  346. uint32_t LowestBitSet() const {
  347. return container_internal::TrailingZeros(mask_) >> Shift;
  348. }
  349. // Returns the index of the highest *abstract* bit set in `self`.
  350. uint32_t HighestBitSet() const {
  351. return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
  352. }
  353. // Returns the number of trailing zero *abstract* bits.
  354. uint32_t TrailingZeros() const {
  355. return container_internal::TrailingZeros(mask_) >> Shift;
  356. }
  357. // Returns the number of leading zero *abstract* bits.
  358. uint32_t LeadingZeros() const {
  359. constexpr int total_significant_bits = SignificantBits << Shift;
  360. constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
  361. return static_cast<uint32_t>(countl_zero(mask_ << extra_bits)) >> Shift;
  362. }
  363. T mask_;
  364. };
  365. // Mask that can be iterable
  366. //
  367. // For example, when `SignificantBits` is 16 and `Shift` is zero, this is just
  368. // an ordinary 16-bit bitset occupying the low 16 bits of `mask`. When
  369. // `SignificantBits` is 8 and `Shift` is 3, abstract bits are represented as
  370. // the bytes `0x00` and `0x80`, and it occupies all 64 bits of the bitmask.
  371. //
  372. // For example:
  373. // for (int i : BitMask<uint32_t, 16>(0b101)) -> yields 0, 2
  374. // for (int i : BitMask<uint64_t, 8, 3>(0x0000000080800000)) -> yields 2, 3
  375. template <class T, int SignificantBits, int Shift = 0>
  376. class BitMask : public NonIterableBitMask<T, SignificantBits, Shift> {
  377. using Base = NonIterableBitMask<T, SignificantBits, Shift>;
  378. static_assert(std::is_unsigned<T>::value, "");
  379. static_assert(Shift == 0 || Shift == 3, "");
  380. public:
  381. explicit BitMask(T mask) : Base(mask) {}
  382. // BitMask is an iterator over the indices of its abstract bits.
  383. using value_type = int;
  384. using iterator = BitMask;
  385. using const_iterator = BitMask;
  386. BitMask& operator++() {
  387. this->mask_ &= (this->mask_ - 1);
  388. return *this;
  389. }
  390. uint32_t operator*() const { return Base::LowestBitSet(); }
  391. BitMask begin() const { return *this; }
  392. BitMask end() const { return BitMask(0); }
  393. private:
  394. friend bool operator==(const BitMask& a, const BitMask& b) {
  395. return a.mask_ == b.mask_;
  396. }
  397. friend bool operator!=(const BitMask& a, const BitMask& b) {
  398. return a.mask_ != b.mask_;
  399. }
  400. };
  401. using h2_t = uint8_t;
  402. // The values here are selected for maximum performance. See the static asserts
  403. // below for details.
  404. // A `ctrl_t` is a single control byte, which can have one of four
  405. // states: empty, deleted, full (which has an associated seven-bit h2_t value)
  406. // and the sentinel. They have the following bit patterns:
  407. //
  408. // empty: 1 0 0 0 0 0 0 0
  409. // deleted: 1 1 1 1 1 1 1 0
  410. // full: 0 h h h h h h h // h represents the hash bits.
  411. // sentinel: 1 1 1 1 1 1 1 1
  412. //
  413. // These values are specifically tuned for SSE-flavored SIMD.
  414. // The static_asserts below detail the source of these choices.
  415. //
  416. // We use an enum class so that when strict aliasing is enabled, the compiler
  417. // knows ctrl_t doesn't alias other types.
  418. enum class ctrl_t : int8_t {
  419. kEmpty = -128, // 0b10000000
  420. kDeleted = -2, // 0b11111110
  421. kSentinel = -1, // 0b11111111
  422. };
  423. static_assert(
  424. (static_cast<int8_t>(ctrl_t::kEmpty) &
  425. static_cast<int8_t>(ctrl_t::kDeleted) &
  426. static_cast<int8_t>(ctrl_t::kSentinel) & 0x80) != 0,
  427. "Special markers need to have the MSB to make checking for them efficient");
  428. static_assert(
  429. ctrl_t::kEmpty < ctrl_t::kSentinel && ctrl_t::kDeleted < ctrl_t::kSentinel,
  430. "ctrl_t::kEmpty and ctrl_t::kDeleted must be smaller than "
  431. "ctrl_t::kSentinel to make the SIMD test of IsEmptyOrDeleted() efficient");
  432. static_assert(
  433. ctrl_t::kSentinel == static_cast<ctrl_t>(-1),
  434. "ctrl_t::kSentinel must be -1 to elide loading it from memory into SIMD "
  435. "registers (pcmpeqd xmm, xmm)");
  436. static_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),
  437. "ctrl_t::kEmpty must be -128 to make the SIMD check for its "
  438. "existence efficient (psignb xmm, xmm)");
  439. static_assert(
  440. (~static_cast<int8_t>(ctrl_t::kEmpty) &
  441. ~static_cast<int8_t>(ctrl_t::kDeleted) &
  442. static_cast<int8_t>(ctrl_t::kSentinel) & 0x7F) != 0,
  443. "ctrl_t::kEmpty and ctrl_t::kDeleted must share an unset bit that is not "
  444. "shared by ctrl_t::kSentinel to make the scalar test for "
  445. "MaskEmptyOrDeleted() efficient");
  446. static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),
  447. "ctrl_t::kDeleted must be -2 to make the implementation of "
  448. "ConvertSpecialToEmptyAndFullToDeleted efficient");
  449. // See definition comment for why this is size 32.
  450. Y_ABSL_DLL extern const ctrl_t kEmptyGroup[32];
  451. // Returns a pointer to a control byte group that can be used by empty tables.
  452. inline ctrl_t* EmptyGroup() {
  453. // Const must be cast away here; no uses of this function will actually write
  454. // to it, because it is only used for empty tables.
  455. return const_cast<ctrl_t*>(kEmptyGroup + 16);
  456. }
  457. // Returns a pointer to a generation to use for an empty hashtable.
  458. GenerationType* EmptyGeneration();
  459. // Returns whether `generation` is a generation for an empty hashtable that
  460. // could be returned by EmptyGeneration().
  461. inline bool IsEmptyGeneration(const GenerationType* generation) {
  462. return *generation == SentinelEmptyGeneration();
  463. }
  464. // Mixes a randomly generated per-process seed with `hash` and `ctrl` to
  465. // randomize insertion order within groups.
  466. bool ShouldInsertBackwards(size_t hash, const ctrl_t* ctrl);
  467. // Returns a per-table, hash salt, which changes on resize. This gets mixed into
  468. // H1 to randomize iteration order per-table.
  469. //
  470. // The seed consists of the ctrl_ pointer, which adds enough entropy to ensure
  471. // non-determinism of iteration order in most cases.
  472. inline size_t PerTableSalt(const ctrl_t* ctrl) {
  473. // The low bits of the pointer have little or no entropy because of
  474. // alignment. We shift the pointer to try to use higher entropy bits. A
  475. // good number seems to be 12 bits, because that aligns with page size.
  476. return reinterpret_cast<uintptr_t>(ctrl) >> 12;
  477. }
  478. // Extracts the H1 portion of a hash: 57 bits mixed with a per-table salt.
  479. inline size_t H1(size_t hash, const ctrl_t* ctrl) {
  480. return (hash >> 7) ^ PerTableSalt(ctrl);
  481. }
  482. // Extracts the H2 portion of a hash: the 7 bits not used for H1.
  483. //
  484. // These are used as an occupied control byte.
  485. inline h2_t H2(size_t hash) { return hash & 0x7F; }
  486. // Helpers for checking the state of a control byte.
  487. inline bool IsEmpty(ctrl_t c) { return c == ctrl_t::kEmpty; }
  488. inline bool IsFull(ctrl_t c) { return c >= static_cast<ctrl_t>(0); }
  489. inline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }
  490. inline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }
  491. #ifdef Y_ABSL_INTERNAL_HAVE_SSE2
  492. // Quick reference guide for intrinsics used below:
  493. //
  494. // * __m128i: An XMM (128-bit) word.
  495. //
  496. // * _mm_setzero_si128: Returns a zero vector.
  497. // * _mm_set1_epi8: Returns a vector with the same i8 in each lane.
  498. //
  499. // * _mm_subs_epi8: Saturating-subtracts two i8 vectors.
  500. // * _mm_and_si128: Ands two i128s together.
  501. // * _mm_or_si128: Ors two i128s together.
  502. // * _mm_andnot_si128: And-nots two i128s together.
  503. //
  504. // * _mm_cmpeq_epi8: Component-wise compares two i8 vectors for equality,
  505. // filling each lane with 0x00 or 0xff.
  506. // * _mm_cmpgt_epi8: Same as above, but using > rather than ==.
  507. //
  508. // * _mm_loadu_si128: Performs an unaligned load of an i128.
  509. // * _mm_storeu_si128: Performs an unaligned store of an i128.
  510. //
  511. // * _mm_sign_epi8: Retains, negates, or zeroes each i8 lane of the first
  512. // argument if the corresponding lane of the second
  513. // argument is positive, negative, or zero, respectively.
  514. // * _mm_movemask_epi8: Selects the sign bit out of each i8 lane and produces a
  515. // bitmask consisting of those bits.
  516. // * _mm_shuffle_epi8: Selects i8s from the first argument, using the low
  517. // four bits of each i8 lane in the second argument as
  518. // indices.
  519. // https://github.com/abseil/abseil-cpp/issues/209
  520. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
  521. // _mm_cmpgt_epi8 is broken under GCC with -funsigned-char
  522. // Work around this by using the portable implementation of Group
  523. // when using -funsigned-char under GCC.
  524. inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {
  525. #if defined(__GNUC__) && !defined(__clang__)
  526. if (std::is_unsigned<char>::value) {
  527. const __m128i mask = _mm_set1_epi8(0x80);
  528. const __m128i diff = _mm_subs_epi8(b, a);
  529. return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);
  530. }
  531. #endif
  532. return _mm_cmpgt_epi8(a, b);
  533. }
  534. struct GroupSse2Impl {
  535. static constexpr size_t kWidth = 16; // the number of slots per group
  536. explicit GroupSse2Impl(const ctrl_t* pos) {
  537. ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));
  538. }
  539. // Returns a bitmask representing the positions of slots that match hash.
  540. BitMask<uint32_t, kWidth> Match(h2_t hash) const {
  541. auto match = _mm_set1_epi8(static_cast<char>(hash));
  542. return BitMask<uint32_t, kWidth>(
  543. static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
  544. }
  545. // Returns a bitmask representing the positions of empty slots.
  546. NonIterableBitMask<uint32_t, kWidth> MaskEmpty() const {
  547. #ifdef Y_ABSL_INTERNAL_HAVE_SSSE3
  548. // This only works because ctrl_t::kEmpty is -128.
  549. return NonIterableBitMask<uint32_t, kWidth>(
  550. static_cast<uint32_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))));
  551. #else
  552. auto match = _mm_set1_epi8(static_cast<char>(ctrl_t::kEmpty));
  553. return NonIterableBitMask<uint32_t, kWidth>(
  554. static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
  555. #endif
  556. }
  557. // Returns a bitmask representing the positions of empty or deleted slots.
  558. NonIterableBitMask<uint32_t, kWidth> MaskEmptyOrDeleted() const {
  559. auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
  560. return NonIterableBitMask<uint32_t, kWidth>(static_cast<uint32_t>(
  561. _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl))));
  562. }
  563. // Returns the number of trailing empty or deleted elements in the group.
  564. uint32_t CountLeadingEmptyOrDeleted() const {
  565. auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
  566. return TrailingZeros(static_cast<uint32_t>(
  567. _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
  568. }
  569. void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
  570. auto msbs = _mm_set1_epi8(static_cast<char>(-128));
  571. auto x126 = _mm_set1_epi8(126);
  572. #ifdef Y_ABSL_INTERNAL_HAVE_SSSE3
  573. auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
  574. #else
  575. auto zero = _mm_setzero_si128();
  576. auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl);
  577. auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126));
  578. #endif
  579. _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);
  580. }
  581. __m128i ctrl;
  582. };
  583. #endif // Y_ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
  584. #if defined(Y_ABSL_INTERNAL_HAVE_ARM_NEON) && defined(Y_ABSL_IS_LITTLE_ENDIAN)
  585. struct GroupAArch64Impl {
  586. static constexpr size_t kWidth = 8;
  587. explicit GroupAArch64Impl(const ctrl_t* pos) {
  588. ctrl = vld1_u8(reinterpret_cast<const uint8_t*>(pos));
  589. }
  590. BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
  591. uint8x8_t dup = vdup_n_u8(hash);
  592. auto mask = vceq_u8(ctrl, dup);
  593. constexpr uint64_t msbs = 0x8080808080808080ULL;
  594. return BitMask<uint64_t, kWidth, 3>(
  595. vget_lane_u64(vreinterpret_u64_u8(mask), 0) & msbs);
  596. }
  597. NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
  598. uint64_t mask =
  599. vget_lane_u64(vreinterpret_u64_u8(vceq_s8(
  600. vdup_n_s8(static_cast<int8_t>(ctrl_t::kEmpty)),
  601. vreinterpret_s8_u8(ctrl))),
  602. 0);
  603. return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
  604. }
  605. NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
  606. uint64_t mask =
  607. vget_lane_u64(vreinterpret_u64_u8(vcgt_s8(
  608. vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
  609. vreinterpret_s8_u8(ctrl))),
  610. 0);
  611. return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
  612. }
  613. uint32_t CountLeadingEmptyOrDeleted() const {
  614. uint64_t mask =
  615. vget_lane_u64(vreinterpret_u64_u8(vcle_s8(
  616. vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
  617. vreinterpret_s8_u8(ctrl))),
  618. 0);
  619. // Similar to MaskEmptyorDeleted() but we invert the logic to invert the
  620. // produced bitfield. We then count number of trailing zeros.
  621. // Clang and GCC optimize countr_zero to rbit+clz without any check for 0,
  622. // so we should be fine.
  623. return static_cast<uint32_t>(countr_zero(mask)) >> 3;
  624. }
  625. void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
  626. uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);
  627. constexpr uint64_t msbs = 0x8080808080808080ULL;
  628. constexpr uint64_t slsbs = 0x0202020202020202ULL;
  629. constexpr uint64_t midbs = 0x7e7e7e7e7e7e7e7eULL;
  630. auto x = slsbs & (mask >> 6);
  631. auto res = (x + midbs) | msbs;
  632. little_endian::Store64(dst, res);
  633. }
  634. uint8x8_t ctrl;
  635. };
  636. #endif // Y_ABSL_INTERNAL_HAVE_ARM_NEON && Y_ABSL_IS_LITTLE_ENDIAN
  637. struct GroupPortableImpl {
  638. static constexpr size_t kWidth = 8;
  639. explicit GroupPortableImpl(const ctrl_t* pos)
  640. : ctrl(little_endian::Load64(pos)) {}
  641. BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
  642. // For the technique, see:
  643. // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
  644. // (Determine if a word has a byte equal to n).
  645. //
  646. // Caveat: there are false positives but:
  647. // - they only occur if there is a real match
  648. // - they never occur on ctrl_t::kEmpty, ctrl_t::kDeleted, ctrl_t::kSentinel
  649. // - they will be handled gracefully by subsequent checks in code
  650. //
  651. // Example:
  652. // v = 0x1716151413121110
  653. // hash = 0x12
  654. // retval = (v - lsbs) & ~v & msbs = 0x0000000080800000
  655. constexpr uint64_t msbs = 0x8080808080808080ULL;
  656. constexpr uint64_t lsbs = 0x0101010101010101ULL;
  657. auto x = ctrl ^ (lsbs * hash);
  658. return BitMask<uint64_t, kWidth, 3>((x - lsbs) & ~x & msbs);
  659. }
  660. NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
  661. constexpr uint64_t msbs = 0x8080808080808080ULL;
  662. return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & (~ctrl << 6)) &
  663. msbs);
  664. }
  665. NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
  666. constexpr uint64_t msbs = 0x8080808080808080ULL;
  667. return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & (~ctrl << 7)) &
  668. msbs);
  669. }
  670. uint32_t CountLeadingEmptyOrDeleted() const {
  671. // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
  672. // kDeleted. We lower all other bits and count number of trailing zeros.
  673. constexpr uint64_t bits = 0x0101010101010101ULL;
  674. return static_cast<uint32_t>(countr_zero((ctrl | ~(ctrl >> 7)) & bits) >>
  675. 3);
  676. }
  677. void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
  678. constexpr uint64_t msbs = 0x8080808080808080ULL;
  679. constexpr uint64_t lsbs = 0x0101010101010101ULL;
  680. auto x = ctrl & msbs;
  681. auto res = (~x + (x >> 7)) & ~lsbs;
  682. little_endian::Store64(dst, res);
  683. }
  684. uint64_t ctrl;
  685. };
  686. #ifdef Y_ABSL_INTERNAL_HAVE_SSE2
  687. using Group = GroupSse2Impl;
  688. #elif defined(Y_ABSL_INTERNAL_HAVE_ARM_NEON) && defined(Y_ABSL_IS_LITTLE_ENDIAN)
  689. using Group = GroupAArch64Impl;
  690. #else
  691. using Group = GroupPortableImpl;
  692. #endif
  693. // When there is an insertion with no reserved growth, we rehash with
  694. // probability `min(1, RehashProbabilityConstant() / capacity())`. Using a
  695. // constant divided by capacity ensures that inserting N elements is still O(N)
  696. // in the average case. Using the constant 16 means that we expect to rehash ~8
  697. // times more often than when generations are disabled. We are adding expected
  698. // rehash_probability * #insertions/capacity_growth = 16/capacity * ((7/8 -
  699. // 7/16) * capacity)/capacity_growth = ~7 extra rehashes per capacity growth.
  700. inline size_t RehashProbabilityConstant() { return 16; }
  701. class CommonFieldsGenerationInfoEnabled {
  702. // A sentinel value for reserved_growth_ indicating that we just ran out of
  703. // reserved growth on the last insertion. When reserve is called and then
  704. // insertions take place, reserved_growth_'s state machine is N, ..., 1,
  705. // kReservedGrowthJustRanOut, 0.
  706. static constexpr size_t kReservedGrowthJustRanOut =
  707. (std::numeric_limits<size_t>::max)();
  708. public:
  709. CommonFieldsGenerationInfoEnabled() = default;
  710. CommonFieldsGenerationInfoEnabled(CommonFieldsGenerationInfoEnabled&& that)
  711. : reserved_growth_(that.reserved_growth_),
  712. reservation_size_(that.reservation_size_),
  713. generation_(that.generation_) {
  714. that.reserved_growth_ = 0;
  715. that.reservation_size_ = 0;
  716. that.generation_ = EmptyGeneration();
  717. }
  718. CommonFieldsGenerationInfoEnabled& operator=(
  719. CommonFieldsGenerationInfoEnabled&&) = default;
  720. // Whether we should rehash on insert in order to detect bugs of using invalid
  721. // references. We rehash on the first insertion after reserved_growth_ reaches
  722. // 0 after a call to reserve. We also do a rehash with low probability
  723. // whenever reserved_growth_ is zero.
  724. bool should_rehash_for_bug_detection_on_insert(const ctrl_t* ctrl,
  725. size_t capacity) const;
  726. void maybe_increment_generation_on_insert() {
  727. if (reserved_growth_ == kReservedGrowthJustRanOut) reserved_growth_ = 0;
  728. if (reserved_growth_ > 0) {
  729. if (--reserved_growth_ == 0) reserved_growth_ = kReservedGrowthJustRanOut;
  730. } else {
  731. *generation_ = NextGeneration(*generation_);
  732. }
  733. }
  734. void reset_reserved_growth(size_t reservation, size_t size) {
  735. reserved_growth_ = reservation - size;
  736. }
  737. size_t reserved_growth() const { return reserved_growth_; }
  738. void set_reserved_growth(size_t r) { reserved_growth_ = r; }
  739. size_t reservation_size() const { return reservation_size_; }
  740. void set_reservation_size(size_t r) { reservation_size_ = r; }
  741. GenerationType generation() const { return *generation_; }
  742. void set_generation(GenerationType g) { *generation_ = g; }
  743. GenerationType* generation_ptr() const { return generation_; }
  744. void set_generation_ptr(GenerationType* g) { generation_ = g; }
  745. private:
  746. // The number of insertions remaining that are guaranteed to not rehash due to
  747. // a prior call to reserve. Note: we store reserved growth in addition to
  748. // reservation size because calls to erase() decrease size_ but don't decrease
  749. // reserved growth.
  750. size_t reserved_growth_ = 0;
  751. // The maximum argument to reserve() since the container was cleared. We need
  752. // to keep track of this, in addition to reserved growth, because we reset
  753. // reserved growth to this when erase(begin(), end()) is called.
  754. size_t reservation_size_ = 0;
  755. // Pointer to the generation counter, which is used to validate iterators and
  756. // is stored in the backing array between the control bytes and the slots.
  757. // Note that we can't store the generation inside the container itself and
  758. // keep a pointer to the container in the iterators because iterators must
  759. // remain valid when the container is moved.
  760. // Note: we could derive this pointer from the control pointer, but it makes
  761. // the code more complicated, and there's a benefit in having the sizes of
  762. // raw_hash_set in sanitizer mode and non-sanitizer mode a bit more different,
  763. // which is that tests are less likely to rely on the size remaining the same.
  764. GenerationType* generation_ = EmptyGeneration();
  765. };
  766. class CommonFieldsGenerationInfoDisabled {
  767. public:
  768. CommonFieldsGenerationInfoDisabled() = default;
  769. CommonFieldsGenerationInfoDisabled(CommonFieldsGenerationInfoDisabled&&) =
  770. default;
  771. CommonFieldsGenerationInfoDisabled& operator=(
  772. CommonFieldsGenerationInfoDisabled&&) = default;
  773. bool should_rehash_for_bug_detection_on_insert(const ctrl_t*, size_t) const {
  774. return false;
  775. }
  776. void maybe_increment_generation_on_insert() {}
  777. void reset_reserved_growth(size_t, size_t) {}
  778. size_t reserved_growth() const { return 0; }
  779. void set_reserved_growth(size_t) {}
  780. size_t reservation_size() const { return 0; }
  781. void set_reservation_size(size_t) {}
  782. GenerationType generation() const { return 0; }
  783. void set_generation(GenerationType) {}
  784. GenerationType* generation_ptr() const { return nullptr; }
  785. void set_generation_ptr(GenerationType*) {}
  786. };
  787. class HashSetIteratorGenerationInfoEnabled {
  788. public:
  789. HashSetIteratorGenerationInfoEnabled() = default;
  790. explicit HashSetIteratorGenerationInfoEnabled(
  791. const GenerationType* generation_ptr)
  792. : generation_ptr_(generation_ptr), generation_(*generation_ptr) {}
  793. GenerationType generation() const { return generation_; }
  794. void reset_generation() { generation_ = *generation_ptr_; }
  795. const GenerationType* generation_ptr() const { return generation_ptr_; }
  796. void set_generation_ptr(const GenerationType* ptr) { generation_ptr_ = ptr; }
  797. private:
  798. const GenerationType* generation_ptr_ = EmptyGeneration();
  799. GenerationType generation_ = *generation_ptr_;
  800. };
  801. class HashSetIteratorGenerationInfoDisabled {
  802. public:
  803. HashSetIteratorGenerationInfoDisabled() = default;
  804. explicit HashSetIteratorGenerationInfoDisabled(const GenerationType*) {}
  805. GenerationType generation() const { return 0; }
  806. void reset_generation() {}
  807. const GenerationType* generation_ptr() const { return nullptr; }
  808. void set_generation_ptr(const GenerationType*) {}
  809. };
  810. #ifdef Y_ABSL_SWISSTABLE_ENABLE_GENERATIONS
  811. using CommonFieldsGenerationInfo = CommonFieldsGenerationInfoEnabled;
  812. using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoEnabled;
  813. #else
  814. using CommonFieldsGenerationInfo = CommonFieldsGenerationInfoDisabled;
  815. using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoDisabled;
  816. #endif
  817. // Returns whether `n` is a valid capacity (i.e., number of slots).
  818. //
  819. // A valid capacity is a non-zero integer `2^m - 1`.
  820. inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
  821. // Computes the offset from the start of the backing allocation of the control
  822. // bytes. growth_left is stored at the beginning of the backing array.
  823. inline size_t ControlOffset() { return sizeof(size_t); }
  824. // Returns the number of "cloned control bytes".
  825. //
  826. // This is the number of control bytes that are present both at the beginning
  827. // of the control byte array and at the end, such that we can create a
  828. // `Group::kWidth`-width probe window starting from any control byte.
  829. constexpr size_t NumClonedBytes() { return Group::kWidth - 1; }
  830. // Given the capacity of a table, computes the offset (from the start of the
  831. // backing allocation) of the generation counter (if it exists).
  832. inline size_t GenerationOffset(size_t capacity) {
  833. assert(IsValidCapacity(capacity));
  834. const size_t num_control_bytes = capacity + 1 + NumClonedBytes();
  835. return ControlOffset() + num_control_bytes;
  836. }
  837. // Given the capacity of a table, computes the offset (from the start of the
  838. // backing allocation) at which the slots begin.
  839. inline size_t SlotOffset(size_t capacity, size_t slot_align) {
  840. assert(IsValidCapacity(capacity));
  841. return (GenerationOffset(capacity) + NumGenerationBytes() + slot_align - 1) &
  842. (~slot_align + 1);
  843. }
  844. // Given the capacity of a table, computes the total size of the backing
  845. // array.
  846. inline size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align) {
  847. return SlotOffset(capacity, slot_align) + capacity * slot_size;
  848. }
  849. // CommonFields hold the fields in raw_hash_set that do not depend
  850. // on template parameters. This allows us to conveniently pass all
  851. // of this state to helper functions as a single argument.
  852. class CommonFields : public CommonFieldsGenerationInfo {
  853. public:
  854. CommonFields() = default;
  855. // Not copyable
  856. CommonFields(const CommonFields&) = delete;
  857. CommonFields& operator=(const CommonFields&) = delete;
  858. // Movable
  859. CommonFields(CommonFields&& that)
  860. : CommonFieldsGenerationInfo(
  861. std::move(static_cast<CommonFieldsGenerationInfo&&>(that))),
  862. // Explicitly copying fields into "this" and then resetting "that"
  863. // fields generates less code then calling y_absl::exchange per field.
  864. control_(that.control()),
  865. slots_(that.slot_array()),
  866. capacity_(that.capacity()),
  867. compressed_tuple_(that.size(), std::move(that.infoz())) {
  868. that.set_control(EmptyGroup());
  869. that.set_slots(nullptr);
  870. that.set_capacity(0);
  871. that.set_size(0);
  872. }
  873. CommonFields& operator=(CommonFields&&) = default;
  874. ctrl_t* control() const { return control_; }
  875. void set_control(ctrl_t* c) { control_ = c; }
  876. void* backing_array_start() const {
  877. // growth_left is stored before control bytes.
  878. assert(reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0);
  879. return control() - sizeof(size_t);
  880. }
  881. // Note: we can't use slots() because Qt defines "slots" as a macro.
  882. void* slot_array() const { return slots_; }
  883. void set_slots(void* s) { slots_ = s; }
  884. // The number of filled slots.
  885. size_t size() const { return compressed_tuple_.template get<0>(); }
  886. void set_size(size_t s) { compressed_tuple_.template get<0>() = s; }
  887. // The total number of available slots.
  888. size_t capacity() const { return capacity_; }
  889. void set_capacity(size_t c) {
  890. assert(c == 0 || IsValidCapacity(c));
  891. capacity_ = c;
  892. }
  893. // The number of slots we can still fill without needing to rehash.
  894. // This is stored in the heap allocation before the control bytes.
  895. size_t growth_left() const {
  896. return *reinterpret_cast<size_t*>(backing_array_start());
  897. }
  898. void set_growth_left(size_t gl) {
  899. *reinterpret_cast<size_t*>(backing_array_start()) = gl;
  900. }
  901. HashtablezInfoHandle& infoz() { return compressed_tuple_.template get<1>(); }
  902. const HashtablezInfoHandle& infoz() const {
  903. return compressed_tuple_.template get<1>();
  904. }
  905. bool should_rehash_for_bug_detection_on_insert() const {
  906. return CommonFieldsGenerationInfo::
  907. should_rehash_for_bug_detection_on_insert(control(), capacity());
  908. }
  909. void reset_reserved_growth(size_t reservation) {
  910. CommonFieldsGenerationInfo::reset_reserved_growth(reservation, size());
  911. }
  912. // The size of the backing array allocation.
  913. size_t alloc_size(size_t slot_size, size_t slot_align) const {
  914. return AllocSize(capacity(), slot_size, slot_align);
  915. }
  916. // Returns the number of control bytes set to kDeleted. For testing only.
  917. size_t TombstonesCount() const {
  918. return static_cast<size_t>(
  919. std::count(control(), control() + capacity(), ctrl_t::kDeleted));
  920. }
  921. private:
  922. // TODO(b/259599413): Investigate removing some of these fields:
  923. // - control/slots can be derived from each other
  924. // - we can use 6 bits for capacity since it's always a power of two minus 1
  925. // The control bytes (and, also, a pointer near to the base of the backing
  926. // array).
  927. //
  928. // This contains `capacity + 1 + NumClonedBytes()` entries, even
  929. // when the table is empty (hence EmptyGroup).
  930. //
  931. // Note that growth_left is stored immediately before this pointer.
  932. ctrl_t* control_ = EmptyGroup();
  933. // The beginning of the slots, located at `SlotOffset()` bytes after
  934. // `control`. May be null for empty tables.
  935. void* slots_ = nullptr;
  936. size_t capacity_ = 0;
  937. // Bundle together size and HashtablezInfoHandle to ensure EBO for
  938. // HashtablezInfoHandle when sampling is turned off.
  939. y_absl::container_internal::CompressedTuple<size_t, HashtablezInfoHandle>
  940. compressed_tuple_{0u, HashtablezInfoHandle{}};
  941. };
  942. template <class Policy, class Hash, class Eq, class Alloc>
  943. class raw_hash_set;
  944. // Returns the next valid capacity after `n`.
  945. inline size_t NextCapacity(size_t n) {
  946. assert(IsValidCapacity(n) || n == 0);
  947. return n * 2 + 1;
  948. }
  949. // Applies the following mapping to every byte in the control array:
  950. // * kDeleted -> kEmpty
  951. // * kEmpty -> kEmpty
  952. // * _ -> kDeleted
  953. // PRECONDITION:
  954. // IsValidCapacity(capacity)
  955. // ctrl[capacity] == ctrl_t::kSentinel
  956. // ctrl[i] != ctrl_t::kSentinel for all i < capacity
  957. void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);
  958. // Converts `n` into the next valid capacity, per `IsValidCapacity`.
  959. inline size_t NormalizeCapacity(size_t n) {
  960. return n ? ~size_t{} >> countl_zero(n) : 1;
  961. }
  962. // General notes on capacity/growth methods below:
  963. // - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
  964. // average of two empty slots per group.
  965. // - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.
  966. // - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we
  967. // never need to probe (the whole table fits in one group) so we don't need a
  968. // load factor less than 1.
  969. // Given `capacity`, applies the load factor; i.e., it returns the maximum
  970. // number of values we should put into the table before a resizing rehash.
  971. inline size_t CapacityToGrowth(size_t capacity) {
  972. assert(IsValidCapacity(capacity));
  973. // `capacity*7/8`
  974. if (Group::kWidth == 8 && capacity == 7) {
  975. // x-x/8 does not work when x==7.
  976. return 6;
  977. }
  978. return capacity - capacity / 8;
  979. }
  980. // Given `growth`, "unapplies" the load factor to find how large the capacity
  981. // should be to stay within the load factor.
  982. //
  983. // This might not be a valid capacity and `NormalizeCapacity()` should be
  984. // called on this.
  985. inline size_t GrowthToLowerboundCapacity(size_t growth) {
  986. // `growth*8/7`
  987. if (Group::kWidth == 8 && growth == 7) {
  988. // x+(x-1)/7 does not work when x==7.
  989. return 8;
  990. }
  991. return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
  992. }
  993. template <class InputIter>
  994. size_t SelectBucketCountForIterRange(InputIter first, InputIter last,
  995. size_t bucket_count) {
  996. if (bucket_count != 0) {
  997. return bucket_count;
  998. }
  999. using InputIterCategory =
  1000. typename std::iterator_traits<InputIter>::iterator_category;
  1001. if (std::is_base_of<std::random_access_iterator_tag,
  1002. InputIterCategory>::value) {
  1003. return GrowthToLowerboundCapacity(
  1004. static_cast<size_t>(std::distance(first, last)));
  1005. }
  1006. return 0;
  1007. }
  1008. constexpr bool SwisstableDebugEnabled() {
  1009. #if defined(Y_ABSL_SWISSTABLE_ENABLE_GENERATIONS) || \
  1010. Y_ABSL_OPTION_HARDENED == 1 || !defined(NDEBUG)
  1011. return true;
  1012. #else
  1013. return false;
  1014. #endif
  1015. }
  1016. inline void AssertIsFull(const ctrl_t* ctrl, GenerationType generation,
  1017. const GenerationType* generation_ptr,
  1018. const char* operation) {
  1019. if (!SwisstableDebugEnabled()) return;
  1020. if (ctrl == nullptr) {
  1021. Y_ABSL_INTERNAL_LOG(FATAL,
  1022. TString(operation) + " called on end() iterator.");
  1023. }
  1024. if (ctrl == EmptyGroup()) {
  1025. Y_ABSL_INTERNAL_LOG(FATAL, TString(operation) +
  1026. " called on default-constructed iterator.");
  1027. }
  1028. if (SwisstableGenerationsEnabled()) {
  1029. if (generation != *generation_ptr) {
  1030. Y_ABSL_INTERNAL_LOG(FATAL,
  1031. TString(operation) +
  1032. " called on invalid iterator. The table could have "
  1033. "rehashed since this iterator was initialized.");
  1034. }
  1035. if (!IsFull(*ctrl)) {
  1036. Y_ABSL_INTERNAL_LOG(
  1037. FATAL,
  1038. TString(operation) +
  1039. " called on invalid iterator. The element was likely erased.");
  1040. }
  1041. } else {
  1042. if (!IsFull(*ctrl)) {
  1043. Y_ABSL_INTERNAL_LOG(
  1044. FATAL,
  1045. TString(operation) +
  1046. " called on invalid iterator. The element might have been erased "
  1047. "or the table might have rehashed. Consider running with "
  1048. "--config=asan to diagnose rehashing issues.");
  1049. }
  1050. }
  1051. }
  1052. // Note that for comparisons, null/end iterators are valid.
  1053. inline void AssertIsValidForComparison(const ctrl_t* ctrl,
  1054. GenerationType generation,
  1055. const GenerationType* generation_ptr) {
  1056. if (!SwisstableDebugEnabled()) return;
  1057. const bool ctrl_is_valid_for_comparison =
  1058. ctrl == nullptr || ctrl == EmptyGroup() || IsFull(*ctrl);
  1059. if (SwisstableGenerationsEnabled()) {
  1060. if (generation != *generation_ptr) {
  1061. Y_ABSL_INTERNAL_LOG(FATAL,
  1062. "Invalid iterator comparison. The table could have "
  1063. "rehashed since this iterator was initialized.");
  1064. }
  1065. if (!ctrl_is_valid_for_comparison) {
  1066. Y_ABSL_INTERNAL_LOG(
  1067. FATAL, "Invalid iterator comparison. The element was likely erased.");
  1068. }
  1069. } else {
  1070. Y_ABSL_HARDENING_ASSERT(
  1071. ctrl_is_valid_for_comparison &&
  1072. "Invalid iterator comparison. The element might have been erased or "
  1073. "the table might have rehashed. Consider running with --config=asan to "
  1074. "diagnose rehashing issues.");
  1075. }
  1076. }
  1077. // If the two iterators come from the same container, then their pointers will
  1078. // interleave such that ctrl_a <= ctrl_b < slot_a <= slot_b or vice/versa.
  1079. // Note: we take slots by reference so that it's not UB if they're uninitialized
  1080. // as long as we don't read them (when ctrl is null).
  1081. inline bool AreItersFromSameContainer(const ctrl_t* ctrl_a,
  1082. const ctrl_t* ctrl_b,
  1083. const void* const& slot_a,
  1084. const void* const& slot_b) {
  1085. // If either control byte is null, then we can't tell.
  1086. if (ctrl_a == nullptr || ctrl_b == nullptr) return true;
  1087. const void* low_slot = slot_a;
  1088. const void* hi_slot = slot_b;
  1089. if (ctrl_a > ctrl_b) {
  1090. std::swap(ctrl_a, ctrl_b);
  1091. std::swap(low_slot, hi_slot);
  1092. }
  1093. return ctrl_b < low_slot && low_slot <= hi_slot;
  1094. }
  1095. // Asserts that two iterators come from the same container.
  1096. // Note: we take slots by reference so that it's not UB if they're uninitialized
  1097. // as long as we don't read them (when ctrl is null).
  1098. inline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b,
  1099. const void* const& slot_a,
  1100. const void* const& slot_b,
  1101. const GenerationType* generation_ptr_a,
  1102. const GenerationType* generation_ptr_b) {
  1103. if (!SwisstableDebugEnabled()) return;
  1104. const bool a_is_default = ctrl_a == EmptyGroup();
  1105. const bool b_is_default = ctrl_b == EmptyGroup();
  1106. if (a_is_default != b_is_default) {
  1107. Y_ABSL_INTERNAL_LOG(
  1108. FATAL,
  1109. "Invalid iterator comparison. Comparing default-constructed iterator "
  1110. "with non-default-constructed iterator.");
  1111. }
  1112. if (a_is_default && b_is_default) return;
  1113. if (SwisstableGenerationsEnabled()) {
  1114. if (generation_ptr_a == generation_ptr_b) return;
  1115. const bool a_is_empty = IsEmptyGeneration(generation_ptr_a);
  1116. const bool b_is_empty = IsEmptyGeneration(generation_ptr_b);
  1117. if (a_is_empty != b_is_empty) {
  1118. Y_ABSL_INTERNAL_LOG(FATAL,
  1119. "Invalid iterator comparison. Comparing iterator from "
  1120. "a non-empty hashtable with an iterator from an empty "
  1121. "hashtable.");
  1122. }
  1123. if (a_is_empty && b_is_empty) {
  1124. Y_ABSL_INTERNAL_LOG(FATAL,
  1125. "Invalid iterator comparison. Comparing iterators from "
  1126. "different empty hashtables.");
  1127. }
  1128. const bool a_is_end = ctrl_a == nullptr;
  1129. const bool b_is_end = ctrl_b == nullptr;
  1130. if (a_is_end || b_is_end) {
  1131. Y_ABSL_INTERNAL_LOG(FATAL,
  1132. "Invalid iterator comparison. Comparing iterator with "
  1133. "an end() iterator from a different hashtable.");
  1134. }
  1135. Y_ABSL_INTERNAL_LOG(FATAL,
  1136. "Invalid iterator comparison. Comparing non-end() "
  1137. "iterators from different hashtables.");
  1138. } else {
  1139. Y_ABSL_HARDENING_ASSERT(
  1140. AreItersFromSameContainer(ctrl_a, ctrl_b, slot_a, slot_b) &&
  1141. "Invalid iterator comparison. The iterators may be from different "
  1142. "containers or the container might have rehashed. Consider running "
  1143. "with --config=asan to diagnose rehashing issues.");
  1144. }
  1145. }
  1146. struct FindInfo {
  1147. size_t offset;
  1148. size_t probe_length;
  1149. };
  1150. // Whether a table is "small". A small table fits entirely into a probing
  1151. // group, i.e., has a capacity < `Group::kWidth`.
  1152. //
  1153. // In small mode we are able to use the whole capacity. The extra control
  1154. // bytes give us at least one "empty" control byte to stop the iteration.
  1155. // This is important to make 1 a valid capacity.
  1156. //
  1157. // In small mode only the first `capacity` control bytes after the sentinel
  1158. // are valid. The rest contain dummy ctrl_t::kEmpty values that do not
  1159. // represent a real slot. This is important to take into account on
  1160. // `find_first_non_full()`, where we never try
  1161. // `ShouldInsertBackwards()` for small tables.
  1162. inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; }
  1163. // Begins a probing operation on `common.control`, using `hash`.
  1164. inline probe_seq<Group::kWidth> probe(const ctrl_t* ctrl, const size_t capacity,
  1165. size_t hash) {
  1166. return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
  1167. }
  1168. inline probe_seq<Group::kWidth> probe(const CommonFields& common, size_t hash) {
  1169. return probe(common.control(), common.capacity(), hash);
  1170. }
  1171. // Probes an array of control bits using a probe sequence derived from `hash`,
  1172. // and returns the offset corresponding to the first deleted or empty slot.
  1173. //
  1174. // Behavior when the entire table is full is undefined.
  1175. //
  1176. // NOTE: this function must work with tables having both empty and deleted
  1177. // slots in the same group. Such tables appear during `erase()`.
  1178. template <typename = void>
  1179. inline FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
  1180. auto seq = probe(common, hash);
  1181. const ctrl_t* ctrl = common.control();
  1182. while (true) {
  1183. Group g{ctrl + seq.offset()};
  1184. auto mask = g.MaskEmptyOrDeleted();
  1185. if (mask) {
  1186. #if !defined(NDEBUG)
  1187. // We want to add entropy even when ASLR is not enabled.
  1188. // In debug build we will randomly insert in either the front or back of
  1189. // the group.
  1190. // TODO(kfm,sbenza): revisit after we do unconditional mixing
  1191. if (!is_small(common.capacity()) && ShouldInsertBackwards(hash, ctrl)) {
  1192. return {seq.offset(mask.HighestBitSet()), seq.index()};
  1193. }
  1194. #endif
  1195. return {seq.offset(mask.LowestBitSet()), seq.index()};
  1196. }
  1197. seq.next();
  1198. assert(seq.index() <= common.capacity() && "full table!");
  1199. }
  1200. }
  1201. // Extern template for inline function keep possibility of inlining.
  1202. // When compiler decided to not inline, no symbols will be added to the
  1203. // corresponding translation unit.
  1204. extern template FindInfo find_first_non_full(const CommonFields&, size_t);
  1205. // Non-inlined version of find_first_non_full for use in less
  1206. // performance critical routines.
  1207. FindInfo find_first_non_full_outofline(const CommonFields&, size_t);
  1208. inline void ResetGrowthLeft(CommonFields& common) {
  1209. common.set_growth_left(CapacityToGrowth(common.capacity()) - common.size());
  1210. }
  1211. // Sets `ctrl` to `{kEmpty, kSentinel, ..., kEmpty}`, marking the entire
  1212. // array as marked as empty.
  1213. inline void ResetCtrl(CommonFields& common, size_t slot_size) {
  1214. const size_t capacity = common.capacity();
  1215. ctrl_t* ctrl = common.control();
  1216. std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
  1217. capacity + 1 + NumClonedBytes());
  1218. ctrl[capacity] = ctrl_t::kSentinel;
  1219. SanitizerPoisonMemoryRegion(common.slot_array(), slot_size * capacity);
  1220. ResetGrowthLeft(common);
  1221. }
  1222. // Sets `ctrl[i]` to `h`.
  1223. //
  1224. // Unlike setting it directly, this function will perform bounds checks and
  1225. // mirror the value to the cloned tail if necessary.
  1226. inline void SetCtrl(const CommonFields& common, size_t i, ctrl_t h,
  1227. size_t slot_size) {
  1228. const size_t capacity = common.capacity();
  1229. assert(i < capacity);
  1230. auto* slot_i = static_cast<const char*>(common.slot_array()) + i * slot_size;
  1231. if (IsFull(h)) {
  1232. SanitizerUnpoisonMemoryRegion(slot_i, slot_size);
  1233. } else {
  1234. SanitizerPoisonMemoryRegion(slot_i, slot_size);
  1235. }
  1236. ctrl_t* ctrl = common.control();
  1237. ctrl[i] = h;
  1238. ctrl[((i - NumClonedBytes()) & capacity) + (NumClonedBytes() & capacity)] = h;
  1239. }
  1240. // Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
  1241. inline void SetCtrl(const CommonFields& common, size_t i, h2_t h,
  1242. size_t slot_size) {
  1243. SetCtrl(common, i, static_cast<ctrl_t>(h), slot_size);
  1244. }
  1245. // growth_left (which is a size_t) is stored with the backing array.
  1246. constexpr size_t BackingArrayAlignment(size_t align_of_slot) {
  1247. return (std::max)(align_of_slot, alignof(size_t));
  1248. }
  1249. template <typename Alloc, size_t SizeOfSlot, size_t AlignOfSlot>
  1250. Y_ABSL_ATTRIBUTE_NOINLINE void InitializeSlots(CommonFields& c, Alloc alloc) {
  1251. assert(c.capacity());
  1252. // Folks with custom allocators often make unwarranted assumptions about the
  1253. // behavior of their classes vis-a-vis trivial destructability and what
  1254. // calls they will or won't make. Avoid sampling for people with custom
  1255. // allocators to get us out of this mess. This is not a hard guarantee but
  1256. // a workaround while we plan the exact guarantee we want to provide.
  1257. const size_t sample_size =
  1258. (std::is_same<Alloc, std::allocator<char>>::value &&
  1259. c.slot_array() == nullptr)
  1260. ? SizeOfSlot
  1261. : 0;
  1262. const size_t cap = c.capacity();
  1263. const size_t alloc_size = AllocSize(cap, SizeOfSlot, AlignOfSlot);
  1264. // growth_left (which is a size_t) is stored with the backing array.
  1265. char* mem = static_cast<char*>(
  1266. Allocate<BackingArrayAlignment(AlignOfSlot)>(&alloc, alloc_size));
  1267. const GenerationType old_generation = c.generation();
  1268. c.set_generation_ptr(
  1269. reinterpret_cast<GenerationType*>(mem + GenerationOffset(cap)));
  1270. c.set_generation(NextGeneration(old_generation));
  1271. c.set_control(reinterpret_cast<ctrl_t*>(mem + ControlOffset()));
  1272. c.set_slots(mem + SlotOffset(cap, AlignOfSlot));
  1273. ResetCtrl(c, SizeOfSlot);
  1274. if (sample_size) {
  1275. c.infoz() = Sample(sample_size);
  1276. }
  1277. c.infoz().RecordStorageChanged(c.size(), cap);
  1278. }
  1279. // PolicyFunctions bundles together some information for a particular
  1280. // raw_hash_set<T, ...> instantiation. This information is passed to
  1281. // type-erased functions that want to do small amounts of type-specific
  1282. // work.
  1283. struct PolicyFunctions {
  1284. size_t slot_size;
  1285. // Returns the hash of the pointed-to slot.
  1286. size_t (*hash_slot)(void* set, void* slot);
  1287. // Transfer the contents of src_slot to dst_slot.
  1288. void (*transfer)(void* set, void* dst_slot, void* src_slot);
  1289. // Deallocate the backing store from common.
  1290. void (*dealloc)(CommonFields& common, const PolicyFunctions& policy);
  1291. };
  1292. // ClearBackingArray clears the backing array, either modifying it in place,
  1293. // or creating a new one based on the value of "reuse".
  1294. // REQUIRES: c.capacity > 0
  1295. void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
  1296. bool reuse);
  1297. // Type-erased version of raw_hash_set::erase_meta_only.
  1298. void EraseMetaOnly(CommonFields& c, ctrl_t* it, size_t slot_size);
  1299. // Function to place in PolicyFunctions::dealloc for raw_hash_sets
  1300. // that are using std::allocator. This allows us to share the same
  1301. // function body for raw_hash_set instantiations that have the
  1302. // same slot alignment.
  1303. template <size_t AlignOfSlot>
  1304. Y_ABSL_ATTRIBUTE_NOINLINE void DeallocateStandard(CommonFields& common,
  1305. const PolicyFunctions& policy) {
  1306. // Unpoison before returning the memory to the allocator.
  1307. SanitizerUnpoisonMemoryRegion(common.slot_array(),
  1308. policy.slot_size * common.capacity());
  1309. std::allocator<char> alloc;
  1310. Deallocate<BackingArrayAlignment(AlignOfSlot)>(
  1311. &alloc, common.backing_array_start(),
  1312. common.alloc_size(policy.slot_size, AlignOfSlot));
  1313. }
  1314. // For trivially relocatable types we use memcpy directly. This allows us to
  1315. // share the same function body for raw_hash_set instantiations that have the
  1316. // same slot size as long as they are relocatable.
  1317. template <size_t SizeOfSlot>
  1318. Y_ABSL_ATTRIBUTE_NOINLINE void TransferRelocatable(void*, void* dst, void* src) {
  1319. memcpy(dst, src, SizeOfSlot);
  1320. }
  1321. // Type-erased version of raw_hash_set::drop_deletes_without_resize.
  1322. void DropDeletesWithoutResize(CommonFields& common,
  1323. const PolicyFunctions& policy, void* tmp_space);
  1324. // A SwissTable.
  1325. //
  1326. // Policy: a policy defines how to perform different operations on
  1327. // the slots of the hashtable (see hash_policy_traits.h for the full interface
  1328. // of policy).
  1329. //
  1330. // Hash: a (possibly polymorphic) functor that hashes keys of the hashtable. The
  1331. // functor should accept a key and return size_t as hash. For best performance
  1332. // it is important that the hash function provides high entropy across all bits
  1333. // of the hash.
  1334. //
  1335. // Eq: a (possibly polymorphic) functor that compares two keys for equality. It
  1336. // should accept two (of possibly different type) keys and return a bool: true
  1337. // if they are equal, false if they are not. If two keys compare equal, then
  1338. // their hash values as defined by Hash MUST be equal.
  1339. //
  1340. // Allocator: an Allocator
  1341. // [https://en.cppreference.com/w/cpp/named_req/Allocator] with which
  1342. // the storage of the hashtable will be allocated and the elements will be
  1343. // constructed and destroyed.
  1344. template <class Policy, class Hash, class Eq, class Alloc>
  1345. class raw_hash_set {
  1346. using PolicyTraits = hash_policy_traits<Policy>;
  1347. using KeyArgImpl =
  1348. KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
  1349. public:
  1350. using init_type = typename PolicyTraits::init_type;
  1351. using key_type = typename PolicyTraits::key_type;
  1352. // TODO(sbenza): Hide slot_type as it is an implementation detail. Needs user
  1353. // code fixes!
  1354. using slot_type = typename PolicyTraits::slot_type;
  1355. using allocator_type = Alloc;
  1356. using size_type = size_t;
  1357. using difference_type = ptrdiff_t;
  1358. using hasher = Hash;
  1359. using key_equal = Eq;
  1360. using policy_type = Policy;
  1361. using value_type = typename PolicyTraits::value_type;
  1362. using reference = value_type&;
  1363. using const_reference = const value_type&;
  1364. using pointer = typename y_absl::allocator_traits<
  1365. allocator_type>::template rebind_traits<value_type>::pointer;
  1366. using const_pointer = typename y_absl::allocator_traits<
  1367. allocator_type>::template rebind_traits<value_type>::const_pointer;
  1368. // Alias used for heterogeneous lookup functions.
  1369. // `key_arg<K>` evaluates to `K` when the functors are transparent and to
  1370. // `key_type` otherwise. It permits template argument deduction on `K` for the
  1371. // transparent case.
  1372. template <class K>
  1373. using key_arg = typename KeyArgImpl::template type<K, key_type>;
  1374. private:
  1375. // Give an early error when key_type is not hashable/eq.
  1376. auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k));
  1377. auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k));
  1378. using AllocTraits = y_absl::allocator_traits<allocator_type>;
  1379. using SlotAlloc = typename y_absl::allocator_traits<
  1380. allocator_type>::template rebind_alloc<slot_type>;
  1381. using SlotAllocTraits = typename y_absl::allocator_traits<
  1382. allocator_type>::template rebind_traits<slot_type>;
  1383. static_assert(std::is_lvalue_reference<reference>::value,
  1384. "Policy::element() must return a reference");
  1385. template <typename T>
  1386. struct SameAsElementReference
  1387. : std::is_same<typename std::remove_cv<
  1388. typename std::remove_reference<reference>::type>::type,
  1389. typename std::remove_cv<
  1390. typename std::remove_reference<T>::type>::type> {};
  1391. // An enabler for insert(T&&): T must be convertible to init_type or be the
  1392. // same as [cv] value_type [ref].
  1393. // Note: we separate SameAsElementReference into its own type to avoid using
  1394. // reference unless we need to. MSVC doesn't seem to like it in some
  1395. // cases.
  1396. template <class T>
  1397. using RequiresInsertable = typename std::enable_if<
  1398. y_absl::disjunction<std::is_convertible<T, init_type>,
  1399. SameAsElementReference<T>>::value,
  1400. int>::type;
  1401. // RequiresNotInit is a workaround for gcc prior to 7.1.
  1402. // See https://godbolt.org/g/Y4xsUh.
  1403. template <class T>
  1404. using RequiresNotInit =
  1405. typename std::enable_if<!std::is_same<T, init_type>::value, int>::type;
  1406. template <class... Ts>
  1407. using IsDecomposable = IsDecomposable<void, PolicyTraits, Hash, Eq, Ts...>;
  1408. public:
  1409. static_assert(std::is_same<pointer, value_type*>::value,
  1410. "Allocators with custom pointer types are not supported");
  1411. static_assert(std::is_same<const_pointer, const value_type*>::value,
  1412. "Allocators with custom pointer types are not supported");
  1413. class iterator : private HashSetIteratorGenerationInfo {
  1414. friend class raw_hash_set;
  1415. public:
  1416. using iterator_category = std::forward_iterator_tag;
  1417. using value_type = typename raw_hash_set::value_type;
  1418. using reference =
  1419. y_absl::conditional_t<PolicyTraits::constant_iterators::value,
  1420. const value_type&, value_type&>;
  1421. using pointer = y_absl::remove_reference_t<reference>*;
  1422. using difference_type = typename raw_hash_set::difference_type;
  1423. iterator() {}
  1424. // PRECONDITION: not an end() iterator.
  1425. reference operator*() const {
  1426. AssertIsFull(ctrl_, generation(), generation_ptr(), "operator*()");
  1427. return PolicyTraits::element(slot_);
  1428. }
  1429. // PRECONDITION: not an end() iterator.
  1430. pointer operator->() const {
  1431. AssertIsFull(ctrl_, generation(), generation_ptr(), "operator->");
  1432. return &operator*();
  1433. }
  1434. // PRECONDITION: not an end() iterator.
  1435. iterator& operator++() {
  1436. AssertIsFull(ctrl_, generation(), generation_ptr(), "operator++");
  1437. ++ctrl_;
  1438. ++slot_;
  1439. skip_empty_or_deleted();
  1440. return *this;
  1441. }
  1442. // PRECONDITION: not an end() iterator.
  1443. iterator operator++(int) {
  1444. auto tmp = *this;
  1445. ++*this;
  1446. return tmp;
  1447. }
  1448. friend bool operator==(const iterator& a, const iterator& b) {
  1449. AssertIsValidForComparison(a.ctrl_, a.generation(), a.generation_ptr());
  1450. AssertIsValidForComparison(b.ctrl_, b.generation(), b.generation_ptr());
  1451. AssertSameContainer(a.ctrl_, b.ctrl_, a.slot_, b.slot_,
  1452. a.generation_ptr(), b.generation_ptr());
  1453. return a.ctrl_ == b.ctrl_;
  1454. }
  1455. friend bool operator!=(const iterator& a, const iterator& b) {
  1456. return !(a == b);
  1457. }
  1458. private:
  1459. iterator(ctrl_t* ctrl, slot_type* slot,
  1460. const GenerationType* generation_ptr)
  1461. : HashSetIteratorGenerationInfo(generation_ptr),
  1462. ctrl_(ctrl),
  1463. slot_(slot) {
  1464. // This assumption helps the compiler know that any non-end iterator is
  1465. // not equal to any end iterator.
  1466. Y_ABSL_ASSUME(ctrl != nullptr);
  1467. }
  1468. // For end() iterators.
  1469. explicit iterator(const GenerationType* generation_ptr)
  1470. : HashSetIteratorGenerationInfo(generation_ptr), ctrl_(nullptr) {}
  1471. // Fixes up `ctrl_` to point to a full by advancing it and `slot_` until
  1472. // they reach one.
  1473. //
  1474. // If a sentinel is reached, we null `ctrl_` out instead.
  1475. void skip_empty_or_deleted() {
  1476. while (IsEmptyOrDeleted(*ctrl_)) {
  1477. uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted();
  1478. ctrl_ += shift;
  1479. slot_ += shift;
  1480. }
  1481. if (Y_ABSL_PREDICT_FALSE(*ctrl_ == ctrl_t::kSentinel)) ctrl_ = nullptr;
  1482. }
  1483. // We use EmptyGroup() for default-constructed iterators so that they can
  1484. // be distinguished from end iterators, which have nullptr ctrl_.
  1485. ctrl_t* ctrl_ = EmptyGroup();
  1486. // To avoid uninitialized member warnings, put slot_ in an anonymous union.
  1487. // The member is not initialized on singleton and end iterators.
  1488. union {
  1489. slot_type* slot_;
  1490. };
  1491. };
  1492. class const_iterator {
  1493. friend class raw_hash_set;
  1494. public:
  1495. using iterator_category = typename iterator::iterator_category;
  1496. using value_type = typename raw_hash_set::value_type;
  1497. using reference = typename raw_hash_set::const_reference;
  1498. using pointer = typename raw_hash_set::const_pointer;
  1499. using difference_type = typename raw_hash_set::difference_type;
  1500. const_iterator() = default;
  1501. // Implicit construction from iterator.
  1502. const_iterator(iterator i) : inner_(std::move(i)) {} // NOLINT
  1503. reference operator*() const { return *inner_; }
  1504. pointer operator->() const { return inner_.operator->(); }
  1505. const_iterator& operator++() {
  1506. ++inner_;
  1507. return *this;
  1508. }
  1509. const_iterator operator++(int) { return inner_++; }
  1510. friend bool operator==(const const_iterator& a, const const_iterator& b) {
  1511. return a.inner_ == b.inner_;
  1512. }
  1513. friend bool operator!=(const const_iterator& a, const const_iterator& b) {
  1514. return !(a == b);
  1515. }
  1516. private:
  1517. const_iterator(const ctrl_t* ctrl, const slot_type* slot,
  1518. const GenerationType* gen)
  1519. : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot), gen) {
  1520. }
  1521. iterator inner_;
  1522. };
  1523. using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>;
  1524. using insert_return_type = InsertReturnType<iterator, node_type>;
  1525. // Note: can't use `= default` due to non-default noexcept (causes
  1526. // problems for some compilers). NOLINTNEXTLINE
  1527. raw_hash_set() noexcept(
  1528. std::is_nothrow_default_constructible<hasher>::value &&
  1529. std::is_nothrow_default_constructible<key_equal>::value &&
  1530. std::is_nothrow_default_constructible<allocator_type>::value) {}
  1531. Y_ABSL_ATTRIBUTE_NOINLINE explicit raw_hash_set(
  1532. size_t bucket_count, const hasher& hash = hasher(),
  1533. const key_equal& eq = key_equal(),
  1534. const allocator_type& alloc = allocator_type())
  1535. : settings_(CommonFields{}, hash, eq, alloc) {
  1536. if (bucket_count) {
  1537. common().set_capacity(NormalizeCapacity(bucket_count));
  1538. initialize_slots();
  1539. }
  1540. }
  1541. raw_hash_set(size_t bucket_count, const hasher& hash,
  1542. const allocator_type& alloc)
  1543. : raw_hash_set(bucket_count, hash, key_equal(), alloc) {}
  1544. raw_hash_set(size_t bucket_count, const allocator_type& alloc)
  1545. : raw_hash_set(bucket_count, hasher(), key_equal(), alloc) {}
  1546. explicit raw_hash_set(const allocator_type& alloc)
  1547. : raw_hash_set(0, hasher(), key_equal(), alloc) {}
  1548. template <class InputIter>
  1549. raw_hash_set(InputIter first, InputIter last, size_t bucket_count = 0,
  1550. const hasher& hash = hasher(), const key_equal& eq = key_equal(),
  1551. const allocator_type& alloc = allocator_type())
  1552. : raw_hash_set(SelectBucketCountForIterRange(first, last, bucket_count),
  1553. hash, eq, alloc) {
  1554. insert(first, last);
  1555. }
  1556. template <class InputIter>
  1557. raw_hash_set(InputIter first, InputIter last, size_t bucket_count,
  1558. const hasher& hash, const allocator_type& alloc)
  1559. : raw_hash_set(first, last, bucket_count, hash, key_equal(), alloc) {}
  1560. template <class InputIter>
  1561. raw_hash_set(InputIter first, InputIter last, size_t bucket_count,
  1562. const allocator_type& alloc)
  1563. : raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {}
  1564. template <class InputIter>
  1565. raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc)
  1566. : raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {}
  1567. // Instead of accepting std::initializer_list<value_type> as the first
  1568. // argument like std::unordered_set<value_type> does, we have two overloads
  1569. // that accept std::initializer_list<T> and std::initializer_list<init_type>.
  1570. // This is advantageous for performance.
  1571. //
  1572. // // Turns {"abc", "def"} into std::initializer_list<TString>, then
  1573. // // copies the strings into the set.
  1574. // std::unordered_set<TString> s = {"abc", "def"};
  1575. //
  1576. // // Turns {"abc", "def"} into std::initializer_list<const char*>, then
  1577. // // copies the strings into the set.
  1578. // y_absl::flat_hash_set<TString> s = {"abc", "def"};
  1579. //
  1580. // The same trick is used in insert().
  1581. //
  1582. // The enabler is necessary to prevent this constructor from triggering where
  1583. // the copy constructor is meant to be called.
  1584. //
  1585. // y_absl::flat_hash_set<int> a, b{a};
  1586. //
  1587. // RequiresNotInit<T> is a workaround for gcc prior to 7.1.
  1588. template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
  1589. raw_hash_set(std::initializer_list<T> init, size_t bucket_count = 0,
  1590. const hasher& hash = hasher(), const key_equal& eq = key_equal(),
  1591. const allocator_type& alloc = allocator_type())
  1592. : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
  1593. raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count = 0,
  1594. const hasher& hash = hasher(), const key_equal& eq = key_equal(),
  1595. const allocator_type& alloc = allocator_type())
  1596. : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
  1597. template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
  1598. raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
  1599. const hasher& hash, const allocator_type& alloc)
  1600. : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
  1601. raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,
  1602. const hasher& hash, const allocator_type& alloc)
  1603. : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
  1604. template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
  1605. raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
  1606. const allocator_type& alloc)
  1607. : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
  1608. raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,
  1609. const allocator_type& alloc)
  1610. : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
  1611. template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
  1612. raw_hash_set(std::initializer_list<T> init, const allocator_type& alloc)
  1613. : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
  1614. raw_hash_set(std::initializer_list<init_type> init,
  1615. const allocator_type& alloc)
  1616. : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
  1617. raw_hash_set(const raw_hash_set& that)
  1618. : raw_hash_set(that, AllocTraits::select_on_container_copy_construction(
  1619. that.alloc_ref())) {}
  1620. raw_hash_set(const raw_hash_set& that, const allocator_type& a)
  1621. : raw_hash_set(0, that.hash_ref(), that.eq_ref(), a) {
  1622. const size_t size = that.size();
  1623. if (size == 0) return;
  1624. reserve(size);
  1625. // Because the table is guaranteed to be empty, we can do something faster
  1626. // than a full `insert`.
  1627. for (const auto& v : that) {
  1628. const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
  1629. auto target = find_first_non_full_outofline(common(), hash);
  1630. SetCtrl(common(), target.offset, H2(hash), sizeof(slot_type));
  1631. emplace_at(target.offset, v);
  1632. common().maybe_increment_generation_on_insert();
  1633. infoz().RecordInsert(hash, target.probe_length);
  1634. }
  1635. common().set_size(size);
  1636. set_growth_left(growth_left() - size);
  1637. }
  1638. Y_ABSL_ATTRIBUTE_NOINLINE raw_hash_set(raw_hash_set&& that) noexcept(
  1639. std::is_nothrow_copy_constructible<hasher>::value &&
  1640. std::is_nothrow_copy_constructible<key_equal>::value &&
  1641. std::is_nothrow_copy_constructible<allocator_type>::value)
  1642. : // Hash, equality and allocator are copied instead of moved because
  1643. // `that` must be left valid. If Hash is std::function<Key>, moving it
  1644. // would create a nullptr functor that cannot be called.
  1645. settings_(y_absl::exchange(that.common(), CommonFields{}),
  1646. that.hash_ref(), that.eq_ref(), that.alloc_ref()) {}
  1647. raw_hash_set(raw_hash_set&& that, const allocator_type& a)
  1648. : settings_(CommonFields{}, that.hash_ref(), that.eq_ref(), a) {
  1649. if (a == that.alloc_ref()) {
  1650. std::swap(common(), that.common());
  1651. } else {
  1652. reserve(that.size());
  1653. // Note: this will copy elements of dense_set and unordered_set instead of
  1654. // moving them. This can be fixed if it ever becomes an issue.
  1655. for (auto& elem : that) insert(std::move(elem));
  1656. }
  1657. }
  1658. raw_hash_set& operator=(const raw_hash_set& that) {
  1659. raw_hash_set tmp(that,
  1660. AllocTraits::propagate_on_container_copy_assignment::value
  1661. ? that.alloc_ref()
  1662. : alloc_ref());
  1663. swap(tmp);
  1664. return *this;
  1665. }
  1666. raw_hash_set& operator=(raw_hash_set&& that) noexcept(
  1667. y_absl::allocator_traits<allocator_type>::is_always_equal::value &&
  1668. std::is_nothrow_move_assignable<hasher>::value &&
  1669. std::is_nothrow_move_assignable<key_equal>::value) {
  1670. // TODO(sbenza): We should only use the operations from the noexcept clause
  1671. // to make sure we actually adhere to that contract.
  1672. // NOLINTNEXTLINE: not returning *this for performance.
  1673. return move_assign(
  1674. std::move(that),
  1675. typename AllocTraits::propagate_on_container_move_assignment());
  1676. }
  1677. ~raw_hash_set() {
  1678. const size_t cap = capacity();
  1679. if (!cap) return;
  1680. destroy_slots();
  1681. // Unpoison before returning the memory to the allocator.
  1682. SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * cap);
  1683. Deallocate<BackingArrayAlignment(alignof(slot_type))>(
  1684. &alloc_ref(), common().backing_array_start(),
  1685. AllocSize(cap, sizeof(slot_type), alignof(slot_type)));
  1686. infoz().Unregister();
  1687. }
  1688. iterator begin() Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1689. auto it = iterator_at(0);
  1690. it.skip_empty_or_deleted();
  1691. return it;
  1692. }
  1693. iterator end() Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1694. return iterator(common().generation_ptr());
  1695. }
  1696. const_iterator begin() const Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1697. return const_cast<raw_hash_set*>(this)->begin();
  1698. }
  1699. const_iterator end() const Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1700. return iterator(common().generation_ptr());
  1701. }
  1702. const_iterator cbegin() const Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1703. return begin();
  1704. }
  1705. const_iterator cend() const Y_ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }
  1706. bool empty() const { return !size(); }
  1707. size_t size() const { return common().size(); }
  1708. size_t capacity() const { return common().capacity(); }
  1709. size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
  1710. Y_ABSL_ATTRIBUTE_REINITIALIZES void clear() {
  1711. // Iterating over this container is O(bucket_count()). When bucket_count()
  1712. // is much greater than size(), iteration becomes prohibitively expensive.
  1713. // For clear() it is more important to reuse the allocated array when the
  1714. // container is small because allocation takes comparatively long time
  1715. // compared to destruction of the elements of the container. So we pick the
  1716. // largest bucket_count() threshold for which iteration is still fast and
  1717. // past that we simply deallocate the array.
  1718. const size_t cap = capacity();
  1719. if (cap == 0) {
  1720. // Already guaranteed to be empty; so nothing to do.
  1721. } else {
  1722. destroy_slots();
  1723. ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/cap < 128);
  1724. }
  1725. common().set_reserved_growth(0);
  1726. common().set_reservation_size(0);
  1727. }
  1728. inline void destroy_slots() {
  1729. const size_t cap = capacity();
  1730. const ctrl_t* ctrl = control();
  1731. slot_type* slot = slot_array();
  1732. for (size_t i = 0; i != cap; ++i) {
  1733. if (IsFull(ctrl[i])) {
  1734. PolicyTraits::destroy(&alloc_ref(), slot + i);
  1735. }
  1736. }
  1737. }
  1738. // This overload kicks in when the argument is an rvalue of insertable and
  1739. // decomposable type other than init_type.
  1740. //
  1741. // flat_hash_map<TString, int> m;
  1742. // m.insert(std::make_pair("abc", 42));
  1743. // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
  1744. // bug.
  1745. template <class T, RequiresInsertable<T> = 0, class T2 = T,
  1746. typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
  1747. T* = nullptr>
  1748. std::pair<iterator, bool> insert(T&& value) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1749. return emplace(std::forward<T>(value));
  1750. }
  1751. // This overload kicks in when the argument is a bitfield or an lvalue of
  1752. // insertable and decomposable type.
  1753. //
  1754. // union { int n : 1; };
  1755. // flat_hash_set<int> s;
  1756. // s.insert(n);
  1757. //
  1758. // flat_hash_set<TString> s;
  1759. // const char* p = "hello";
  1760. // s.insert(p);
  1761. //
  1762. template <
  1763. class T, RequiresInsertable<const T&> = 0,
  1764. typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
  1765. std::pair<iterator, bool> insert(const T& value)
  1766. Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1767. return emplace(value);
  1768. }
  1769. // This overload kicks in when the argument is an rvalue of init_type. Its
  1770. // purpose is to handle brace-init-list arguments.
  1771. //
  1772. // flat_hash_map<TString, int> s;
  1773. // s.insert({"abc", 42});
  1774. std::pair<iterator, bool> insert(init_type&& value)
  1775. Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1776. return emplace(std::move(value));
  1777. }
  1778. // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
  1779. // bug.
  1780. template <class T, RequiresInsertable<T> = 0, class T2 = T,
  1781. typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
  1782. T* = nullptr>
  1783. iterator insert(const_iterator, T&& value) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1784. return insert(std::forward<T>(value)).first;
  1785. }
  1786. template <
  1787. class T, RequiresInsertable<const T&> = 0,
  1788. typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
  1789. iterator insert(const_iterator,
  1790. const T& value) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1791. return insert(value).first;
  1792. }
  1793. iterator insert(const_iterator,
  1794. init_type&& value) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1795. return insert(std::move(value)).first;
  1796. }
  1797. template <class InputIt>
  1798. void insert(InputIt first, InputIt last) {
  1799. for (; first != last; ++first) emplace(*first);
  1800. }
  1801. template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0>
  1802. void insert(std::initializer_list<T> ilist) {
  1803. insert(ilist.begin(), ilist.end());
  1804. }
  1805. void insert(std::initializer_list<init_type> ilist) {
  1806. insert(ilist.begin(), ilist.end());
  1807. }
  1808. insert_return_type insert(node_type&& node) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1809. if (!node) return {end(), false, node_type()};
  1810. const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));
  1811. auto res = PolicyTraits::apply(
  1812. InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))},
  1813. elem);
  1814. if (res.second) {
  1815. CommonAccess::Reset(&node);
  1816. return {res.first, true, node_type()};
  1817. } else {
  1818. return {res.first, false, std::move(node)};
  1819. }
  1820. }
  1821. iterator insert(const_iterator,
  1822. node_type&& node) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1823. auto res = insert(std::move(node));
  1824. node = std::move(res.node);
  1825. return res.position;
  1826. }
  1827. // This overload kicks in if we can deduce the key from args. This enables us
  1828. // to avoid constructing value_type if an entry with the same key already
  1829. // exists.
  1830. //
  1831. // For example:
  1832. //
  1833. // flat_hash_map<TString, TString> m = {{"abc", "def"}};
  1834. // // Creates no TString copies and makes no heap allocations.
  1835. // m.emplace("abc", "xyz");
  1836. template <class... Args, typename std::enable_if<
  1837. IsDecomposable<Args...>::value, int>::type = 0>
  1838. std::pair<iterator, bool> emplace(Args&&... args)
  1839. Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1840. return PolicyTraits::apply(EmplaceDecomposable{*this},
  1841. std::forward<Args>(args)...);
  1842. }
  1843. // This overload kicks in if we cannot deduce the key from args. It constructs
  1844. // value_type unconditionally and then either moves it into the table or
  1845. // destroys.
  1846. template <class... Args, typename std::enable_if<
  1847. !IsDecomposable<Args...>::value, int>::type = 0>
  1848. std::pair<iterator, bool> emplace(Args&&... args)
  1849. Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1850. alignas(slot_type) unsigned char raw[sizeof(slot_type)];
  1851. slot_type* slot = reinterpret_cast<slot_type*>(&raw);
  1852. PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
  1853. const auto& elem = PolicyTraits::element(slot);
  1854. return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem);
  1855. }
  1856. template <class... Args>
  1857. iterator emplace_hint(const_iterator,
  1858. Args&&... args) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1859. return emplace(std::forward<Args>(args)...).first;
  1860. }
  1861. // Extension API: support for lazy emplace.
  1862. //
  1863. // Looks up key in the table. If found, returns the iterator to the element.
  1864. // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`,
  1865. // and returns an iterator to the new element.
  1866. //
  1867. // `f` must abide by several restrictions:
  1868. // - it MUST call `raw_hash_set::constructor` with arguments as if a
  1869. // `raw_hash_set::value_type` is constructed,
  1870. // - it MUST NOT access the container before the call to
  1871. // `raw_hash_set::constructor`, and
  1872. // - it MUST NOT erase the lazily emplaced element.
  1873. // Doing any of these is undefined behavior.
  1874. //
  1875. // For example:
  1876. //
  1877. // std::unordered_set<ArenaString> s;
  1878. // // Makes ArenaStr even if "abc" is in the map.
  1879. // s.insert(ArenaString(&arena, "abc"));
  1880. //
  1881. // flat_hash_set<ArenaStr> s;
  1882. // // Makes ArenaStr only if "abc" is not in the map.
  1883. // s.lazy_emplace("abc", [&](const constructor& ctor) {
  1884. // ctor(&arena, "abc");
  1885. // });
  1886. //
  1887. // WARNING: This API is currently experimental. If there is a way to implement
  1888. // the same thing with the rest of the API, prefer that.
  1889. class constructor {
  1890. friend class raw_hash_set;
  1891. public:
  1892. template <class... Args>
  1893. void operator()(Args&&... args) const {
  1894. assert(*slot_);
  1895. PolicyTraits::construct(alloc_, *slot_, std::forward<Args>(args)...);
  1896. *slot_ = nullptr;
  1897. }
  1898. private:
  1899. constructor(allocator_type* a, slot_type** slot) : alloc_(a), slot_(slot) {}
  1900. allocator_type* alloc_;
  1901. slot_type** slot_;
  1902. };
  1903. template <class K = key_type, class F>
  1904. iterator lazy_emplace(const key_arg<K>& key,
  1905. F&& f) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1906. auto res = find_or_prepare_insert(key);
  1907. if (res.second) {
  1908. slot_type* slot = slot_array() + res.first;
  1909. std::forward<F>(f)(constructor(&alloc_ref(), &slot));
  1910. assert(!slot);
  1911. }
  1912. return iterator_at(res.first);
  1913. }
  1914. // Extension API: support for heterogeneous keys.
  1915. //
  1916. // std::unordered_set<TString> s;
  1917. // // Turns "abc" into TString.
  1918. // s.erase("abc");
  1919. //
  1920. // flat_hash_set<TString> s;
  1921. // // Uses "abc" directly without copying it into TString.
  1922. // s.erase("abc");
  1923. template <class K = key_type>
  1924. size_type erase(const key_arg<K>& key) {
  1925. auto it = find(key);
  1926. if (it == end()) return 0;
  1927. erase(it);
  1928. return 1;
  1929. }
  1930. // Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`,
  1931. // this method returns void to reduce algorithmic complexity to O(1). The
  1932. // iterator is invalidated, so any increment should be done before calling
  1933. // erase. In order to erase while iterating across a map, use the following
  1934. // idiom (which also works for standard containers):
  1935. //
  1936. // for (auto it = m.begin(), end = m.end(); it != end;) {
  1937. // // `erase()` will invalidate `it`, so advance `it` first.
  1938. // auto copy_it = it++;
  1939. // if (<pred>) {
  1940. // m.erase(copy_it);
  1941. // }
  1942. // }
  1943. void erase(const_iterator cit) { erase(cit.inner_); }
  1944. // This overload is necessary because otherwise erase<K>(const K&) would be
  1945. // a better match if non-const iterator is passed as an argument.
  1946. void erase(iterator it) {
  1947. AssertIsFull(it.ctrl_, it.generation(), it.generation_ptr(), "erase()");
  1948. PolicyTraits::destroy(&alloc_ref(), it.slot_);
  1949. erase_meta_only(it);
  1950. }
  1951. iterator erase(const_iterator first,
  1952. const_iterator last) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  1953. // We check for empty first because ClearBackingArray requires that
  1954. // capacity() > 0 as a precondition.
  1955. if (empty()) return end();
  1956. if (first == begin() && last == end()) {
  1957. // TODO(ezb): we access control bytes in destroy_slots so it could make
  1958. // sense to combine destroy_slots and ClearBackingArray to avoid cache
  1959. // misses when the table is large. Note that we also do this in clear().
  1960. destroy_slots();
  1961. ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/true);
  1962. common().set_reserved_growth(common().reservation_size());
  1963. return end();
  1964. }
  1965. while (first != last) {
  1966. erase(first++);
  1967. }
  1968. return last.inner_;
  1969. }
  1970. // Moves elements from `src` into `this`.
  1971. // If the element already exists in `this`, it is left unmodified in `src`.
  1972. template <typename H, typename E>
  1973. void merge(raw_hash_set<Policy, H, E, Alloc>& src) { // NOLINT
  1974. assert(this != &src);
  1975. for (auto it = src.begin(), e = src.end(); it != e;) {
  1976. auto next = std::next(it);
  1977. if (PolicyTraits::apply(InsertSlot<false>{*this, std::move(*it.slot_)},
  1978. PolicyTraits::element(it.slot_))
  1979. .second) {
  1980. src.erase_meta_only(it);
  1981. }
  1982. it = next;
  1983. }
  1984. }
  1985. template <typename H, typename E>
  1986. void merge(raw_hash_set<Policy, H, E, Alloc>&& src) {
  1987. merge(src);
  1988. }
  1989. node_type extract(const_iterator position) {
  1990. AssertIsFull(position.inner_.ctrl_, position.inner_.generation(),
  1991. position.inner_.generation_ptr(), "extract()");
  1992. auto node =
  1993. CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_);
  1994. erase_meta_only(position);
  1995. return node;
  1996. }
  1997. template <
  1998. class K = key_type,
  1999. typename std::enable_if<!std::is_same<K, iterator>::value, int>::type = 0>
  2000. node_type extract(const key_arg<K>& key) {
  2001. auto it = find(key);
  2002. return it == end() ? node_type() : extract(const_iterator{it});
  2003. }
  2004. void swap(raw_hash_set& that) noexcept(
  2005. IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
  2006. IsNoThrowSwappable<allocator_type>(
  2007. typename AllocTraits::propagate_on_container_swap{})) {
  2008. using std::swap;
  2009. swap(common(), that.common());
  2010. swap(hash_ref(), that.hash_ref());
  2011. swap(eq_ref(), that.eq_ref());
  2012. SwapAlloc(alloc_ref(), that.alloc_ref(),
  2013. typename AllocTraits::propagate_on_container_swap{});
  2014. }
  2015. void rehash(size_t n) {
  2016. if (n == 0 && capacity() == 0) return;
  2017. if (n == 0 && size() == 0) {
  2018. ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/false);
  2019. return;
  2020. }
  2021. // bitor is a faster way of doing `max` here. We will round up to the next
  2022. // power-of-2-minus-1, so bitor is good enough.
  2023. auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
  2024. // n == 0 unconditionally rehashes as per the standard.
  2025. if (n == 0 || m > capacity()) {
  2026. resize(m);
  2027. // This is after resize, to ensure that we have completed the allocation
  2028. // and have potentially sampled the hashtable.
  2029. infoz().RecordReservation(n);
  2030. }
  2031. }
  2032. void reserve(size_t n) {
  2033. if (n > size() + growth_left()) {
  2034. size_t m = GrowthToLowerboundCapacity(n);
  2035. resize(NormalizeCapacity(m));
  2036. // This is after resize, to ensure that we have completed the allocation
  2037. // and have potentially sampled the hashtable.
  2038. infoz().RecordReservation(n);
  2039. }
  2040. common().reset_reserved_growth(n);
  2041. common().set_reservation_size(n);
  2042. }
  2043. // Extension API: support for heterogeneous keys.
  2044. //
  2045. // std::unordered_set<TString> s;
  2046. // // Turns "abc" into TString.
  2047. // s.count("abc");
  2048. //
  2049. // ch_set<TString> s;
  2050. // // Uses "abc" directly without copying it into TString.
  2051. // s.count("abc");
  2052. template <class K = key_type>
  2053. size_t count(const key_arg<K>& key) const {
  2054. return find(key) == end() ? 0 : 1;
  2055. }
  2056. // Issues CPU prefetch instructions for the memory needed to find or insert
  2057. // a key. Like all lookup functions, this support heterogeneous keys.
  2058. //
  2059. // NOTE: This is a very low level operation and should not be used without
  2060. // specific benchmarks indicating its importance.
  2061. template <class K = key_type>
  2062. void prefetch(const key_arg<K>& key) const {
  2063. (void)key;
  2064. // Avoid probing if we won't be able to prefetch the addresses received.
  2065. #ifdef Y_ABSL_HAVE_PREFETCH
  2066. prefetch_heap_block();
  2067. auto seq = probe(common(), hash_ref()(key));
  2068. PrefetchToLocalCache(control() + seq.offset());
  2069. PrefetchToLocalCache(slot_array() + seq.offset());
  2070. #endif // Y_ABSL_HAVE_PREFETCH
  2071. }
  2072. // The API of find() has two extensions.
  2073. //
  2074. // 1. The hash can be passed by the user. It must be equal to the hash of the
  2075. // key.
  2076. //
  2077. // 2. The type of the key argument doesn't have to be key_type. This is so
  2078. // called heterogeneous key support.
  2079. template <class K = key_type>
  2080. iterator find(const key_arg<K>& key,
  2081. size_t hash) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  2082. auto seq = probe(common(), hash);
  2083. slot_type* slot_ptr = slot_array();
  2084. const ctrl_t* ctrl = control();
  2085. while (true) {
  2086. Group g{ctrl + seq.offset()};
  2087. for (uint32_t i : g.Match(H2(hash))) {
  2088. if (Y_ABSL_PREDICT_TRUE(PolicyTraits::apply(
  2089. EqualElement<K>{key, eq_ref()},
  2090. PolicyTraits::element(slot_ptr + seq.offset(i)))))
  2091. return iterator_at(seq.offset(i));
  2092. }
  2093. if (Y_ABSL_PREDICT_TRUE(g.MaskEmpty())) return end();
  2094. seq.next();
  2095. assert(seq.index() <= capacity() && "full table!");
  2096. }
  2097. }
  2098. template <class K = key_type>
  2099. iterator find(const key_arg<K>& key) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  2100. prefetch_heap_block();
  2101. return find(key, hash_ref()(key));
  2102. }
  2103. template <class K = key_type>
  2104. const_iterator find(const key_arg<K>& key,
  2105. size_t hash) const Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  2106. return const_cast<raw_hash_set*>(this)->find(key, hash);
  2107. }
  2108. template <class K = key_type>
  2109. const_iterator find(const key_arg<K>& key) const
  2110. Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  2111. prefetch_heap_block();
  2112. return find(key, hash_ref()(key));
  2113. }
  2114. template <class K = key_type>
  2115. bool contains(const key_arg<K>& key) const {
  2116. return find(key) != end();
  2117. }
  2118. template <class K = key_type>
  2119. std::pair<iterator, iterator> equal_range(const key_arg<K>& key)
  2120. Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  2121. auto it = find(key);
  2122. if (it != end()) return {it, std::next(it)};
  2123. return {it, it};
  2124. }
  2125. template <class K = key_type>
  2126. std::pair<const_iterator, const_iterator> equal_range(
  2127. const key_arg<K>& key) const Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  2128. auto it = find(key);
  2129. if (it != end()) return {it, std::next(it)};
  2130. return {it, it};
  2131. }
  2132. size_t bucket_count() const { return capacity(); }
  2133. float load_factor() const {
  2134. return capacity() ? static_cast<double>(size()) / capacity() : 0.0;
  2135. }
  2136. float max_load_factor() const { return 1.0f; }
  2137. void max_load_factor(float) {
  2138. // Does nothing.
  2139. }
  2140. hasher hash_function() const { return hash_ref(); }
  2141. key_equal key_eq() const { return eq_ref(); }
  2142. allocator_type get_allocator() const { return alloc_ref(); }
  2143. friend bool operator==(const raw_hash_set& a, const raw_hash_set& b) {
  2144. if (a.size() != b.size()) return false;
  2145. const raw_hash_set* outer = &a;
  2146. const raw_hash_set* inner = &b;
  2147. if (outer->capacity() > inner->capacity()) std::swap(outer, inner);
  2148. for (const value_type& elem : *outer)
  2149. if (!inner->has_element(elem)) return false;
  2150. return true;
  2151. }
  2152. friend bool operator!=(const raw_hash_set& a, const raw_hash_set& b) {
  2153. return !(a == b);
  2154. }
  2155. template <typename H>
  2156. friend typename std::enable_if<H::template is_hashable<value_type>::value,
  2157. H>::type
  2158. AbslHashValue(H h, const raw_hash_set& s) {
  2159. return H::combine(H::combine_unordered(std::move(h), s.begin(), s.end()),
  2160. s.size());
  2161. }
  2162. friend void swap(raw_hash_set& a,
  2163. raw_hash_set& b) noexcept(noexcept(a.swap(b))) {
  2164. a.swap(b);
  2165. }
  2166. private:
  2167. template <class Container, typename Enabler>
  2168. friend struct y_absl::container_internal::hashtable_debug_internal::
  2169. HashtableDebugAccess;
  2170. struct FindElement {
  2171. template <class K, class... Args>
  2172. const_iterator operator()(const K& key, Args&&...) const {
  2173. return s.find(key);
  2174. }
  2175. const raw_hash_set& s;
  2176. };
  2177. struct HashElement {
  2178. template <class K, class... Args>
  2179. size_t operator()(const K& key, Args&&...) const {
  2180. return h(key);
  2181. }
  2182. const hasher& h;
  2183. };
  2184. template <class K1>
  2185. struct EqualElement {
  2186. template <class K2, class... Args>
  2187. bool operator()(const K2& lhs, Args&&...) const {
  2188. return eq(lhs, rhs);
  2189. }
  2190. const K1& rhs;
  2191. const key_equal& eq;
  2192. };
  2193. struct EmplaceDecomposable {
  2194. template <class K, class... Args>
  2195. std::pair<iterator, bool> operator()(const K& key, Args&&... args) const {
  2196. auto res = s.find_or_prepare_insert(key);
  2197. if (res.second) {
  2198. s.emplace_at(res.first, std::forward<Args>(args)...);
  2199. }
  2200. return {s.iterator_at(res.first), res.second};
  2201. }
  2202. raw_hash_set& s;
  2203. };
  2204. template <bool do_destroy>
  2205. struct InsertSlot {
  2206. template <class K, class... Args>
  2207. std::pair<iterator, bool> operator()(const K& key, Args&&...) && {
  2208. auto res = s.find_or_prepare_insert(key);
  2209. if (res.second) {
  2210. PolicyTraits::transfer(&s.alloc_ref(), s.slot_array() + res.first,
  2211. &slot);
  2212. } else if (do_destroy) {
  2213. PolicyTraits::destroy(&s.alloc_ref(), &slot);
  2214. }
  2215. return {s.iterator_at(res.first), res.second};
  2216. }
  2217. raw_hash_set& s;
  2218. // Constructed slot. Either moved into place or destroyed.
  2219. slot_type&& slot;
  2220. };
  2221. // Erases, but does not destroy, the value pointed to by `it`.
  2222. //
  2223. // This merely updates the pertinent control byte. This can be used in
  2224. // conjunction with Policy::transfer to move the object to another place.
  2225. void erase_meta_only(const_iterator it) {
  2226. EraseMetaOnly(common(), it.inner_.ctrl_, sizeof(slot_type));
  2227. }
  2228. // Allocates a backing array for `self` and initializes its control bytes.
  2229. // This reads `capacity` and updates all other fields based on the result of
  2230. // the allocation.
  2231. //
  2232. // This does not free the currently held array; `capacity` must be nonzero.
  2233. inline void initialize_slots() {
  2234. // People are often sloppy with the exact type of their allocator (sometimes
  2235. // it has an extra const or is missing the pair, but rebinds made it work
  2236. // anyway).
  2237. using CharAlloc =
  2238. typename y_absl::allocator_traits<Alloc>::template rebind_alloc<char>;
  2239. InitializeSlots<CharAlloc, sizeof(slot_type), alignof(slot_type)>(
  2240. common(), CharAlloc(alloc_ref()));
  2241. }
  2242. Y_ABSL_ATTRIBUTE_NOINLINE void resize(size_t new_capacity) {
  2243. assert(IsValidCapacity(new_capacity));
  2244. auto* old_ctrl = control();
  2245. auto* old_slots = slot_array();
  2246. const size_t old_capacity = common().capacity();
  2247. common().set_capacity(new_capacity);
  2248. initialize_slots();
  2249. auto* new_slots = slot_array();
  2250. size_t total_probe_length = 0;
  2251. for (size_t i = 0; i != old_capacity; ++i) {
  2252. if (IsFull(old_ctrl[i])) {
  2253. size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
  2254. PolicyTraits::element(old_slots + i));
  2255. auto target = find_first_non_full(common(), hash);
  2256. size_t new_i = target.offset;
  2257. total_probe_length += target.probe_length;
  2258. SetCtrl(common(), new_i, H2(hash), sizeof(slot_type));
  2259. PolicyTraits::transfer(&alloc_ref(), new_slots + new_i, old_slots + i);
  2260. }
  2261. }
  2262. if (old_capacity) {
  2263. SanitizerUnpoisonMemoryRegion(old_slots,
  2264. sizeof(slot_type) * old_capacity);
  2265. Deallocate<BackingArrayAlignment(alignof(slot_type))>(
  2266. &alloc_ref(), old_ctrl - ControlOffset(),
  2267. AllocSize(old_capacity, sizeof(slot_type), alignof(slot_type)));
  2268. }
  2269. infoz().RecordRehash(total_probe_length);
  2270. }
  2271. // Prunes control bytes to remove as many tombstones as possible.
  2272. //
  2273. // See the comment on `rehash_and_grow_if_necessary()`.
  2274. inline void drop_deletes_without_resize() {
  2275. // Stack-allocate space for swapping elements.
  2276. alignas(slot_type) unsigned char tmp[sizeof(slot_type)];
  2277. DropDeletesWithoutResize(common(), GetPolicyFunctions(), tmp);
  2278. }
  2279. // Called whenever the table *might* need to conditionally grow.
  2280. //
  2281. // This function is an optimization opportunity to perform a rehash even when
  2282. // growth is unnecessary, because vacating tombstones is beneficial for
  2283. // performance in the long-run.
  2284. void rehash_and_grow_if_necessary() {
  2285. const size_t cap = capacity();
  2286. if (cap > Group::kWidth &&
  2287. // Do these calculations in 64-bit to avoid overflow.
  2288. size() * uint64_t{32} <= cap * uint64_t{25}) {
  2289. // Squash DELETED without growing if there is enough capacity.
  2290. //
  2291. // Rehash in place if the current size is <= 25/32 of capacity.
  2292. // Rationale for such a high factor: 1) drop_deletes_without_resize() is
  2293. // faster than resize, and 2) it takes quite a bit of work to add
  2294. // tombstones. In the worst case, seems to take approximately 4
  2295. // insert/erase pairs to create a single tombstone and so if we are
  2296. // rehashing because of tombstones, we can afford to rehash-in-place as
  2297. // long as we are reclaiming at least 1/8 the capacity without doing more
  2298. // than 2X the work. (Where "work" is defined to be size() for rehashing
  2299. // or rehashing in place, and 1 for an insert or erase.) But rehashing in
  2300. // place is faster per operation than inserting or even doubling the size
  2301. // of the table, so we actually afford to reclaim even less space from a
  2302. // resize-in-place. The decision is to rehash in place if we can reclaim
  2303. // at about 1/8th of the usable capacity (specifically 3/28 of the
  2304. // capacity) which means that the total cost of rehashing will be a small
  2305. // fraction of the total work.
  2306. //
  2307. // Here is output of an experiment using the BM_CacheInSteadyState
  2308. // benchmark running the old case (where we rehash-in-place only if we can
  2309. // reclaim at least 7/16*capacity) vs. this code (which rehashes in place
  2310. // if we can recover 3/32*capacity).
  2311. //
  2312. // Note that although in the worst-case number of rehashes jumped up from
  2313. // 15 to 190, but the number of operations per second is almost the same.
  2314. //
  2315. // Abridged output of running BM_CacheInSteadyState benchmark from
  2316. // raw_hash_set_benchmark. N is the number of insert/erase operations.
  2317. //
  2318. // | OLD (recover >= 7/16 | NEW (recover >= 3/32)
  2319. // size | N/s LoadFactor NRehashes | N/s LoadFactor NRehashes
  2320. // 448 | 145284 0.44 18 | 140118 0.44 19
  2321. // 493 | 152546 0.24 11 | 151417 0.48 28
  2322. // 538 | 151439 0.26 11 | 151152 0.53 38
  2323. // 583 | 151765 0.28 11 | 150572 0.57 50
  2324. // 628 | 150241 0.31 11 | 150853 0.61 66
  2325. // 672 | 149602 0.33 12 | 150110 0.66 90
  2326. // 717 | 149998 0.35 12 | 149531 0.70 129
  2327. // 762 | 149836 0.37 13 | 148559 0.74 190
  2328. // 807 | 149736 0.39 14 | 151107 0.39 14
  2329. // 852 | 150204 0.42 15 | 151019 0.42 15
  2330. drop_deletes_without_resize();
  2331. } else {
  2332. // Otherwise grow the container.
  2333. resize(NextCapacity(cap));
  2334. }
  2335. }
  2336. bool has_element(const value_type& elem) const {
  2337. size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, elem);
  2338. auto seq = probe(common(), hash);
  2339. const ctrl_t* ctrl = control();
  2340. while (true) {
  2341. Group g{ctrl + seq.offset()};
  2342. for (uint32_t i : g.Match(H2(hash))) {
  2343. if (Y_ABSL_PREDICT_TRUE(
  2344. PolicyTraits::element(slot_array() + seq.offset(i)) == elem))
  2345. return true;
  2346. }
  2347. if (Y_ABSL_PREDICT_TRUE(g.MaskEmpty())) return false;
  2348. seq.next();
  2349. assert(seq.index() <= capacity() && "full table!");
  2350. }
  2351. return false;
  2352. }
  2353. // TODO(alkis): Optimize this assuming *this and that don't overlap.
  2354. raw_hash_set& move_assign(raw_hash_set&& that, std::true_type) {
  2355. raw_hash_set tmp(std::move(that));
  2356. swap(tmp);
  2357. return *this;
  2358. }
  2359. raw_hash_set& move_assign(raw_hash_set&& that, std::false_type) {
  2360. raw_hash_set tmp(std::move(that), alloc_ref());
  2361. swap(tmp);
  2362. return *this;
  2363. }
  2364. protected:
  2365. // Attempts to find `key` in the table; if it isn't found, returns a slot that
  2366. // the value can be inserted into, with the control byte already set to
  2367. // `key`'s H2.
  2368. template <class K>
  2369. std::pair<size_t, bool> find_or_prepare_insert(const K& key) {
  2370. prefetch_heap_block();
  2371. auto hash = hash_ref()(key);
  2372. auto seq = probe(common(), hash);
  2373. const ctrl_t* ctrl = control();
  2374. while (true) {
  2375. Group g{ctrl + seq.offset()};
  2376. for (uint32_t i : g.Match(H2(hash))) {
  2377. if (Y_ABSL_PREDICT_TRUE(PolicyTraits::apply(
  2378. EqualElement<K>{key, eq_ref()},
  2379. PolicyTraits::element(slot_array() + seq.offset(i)))))
  2380. return {seq.offset(i), false};
  2381. }
  2382. if (Y_ABSL_PREDICT_TRUE(g.MaskEmpty())) break;
  2383. seq.next();
  2384. assert(seq.index() <= capacity() && "full table!");
  2385. }
  2386. return {prepare_insert(hash), true};
  2387. }
  2388. // Given the hash of a value not currently in the table, finds the next
  2389. // viable slot index to insert it at.
  2390. //
  2391. // REQUIRES: At least one non-full slot available.
  2392. size_t prepare_insert(size_t hash) Y_ABSL_ATTRIBUTE_NOINLINE {
  2393. const bool rehash_for_bug_detection =
  2394. common().should_rehash_for_bug_detection_on_insert();
  2395. if (rehash_for_bug_detection) {
  2396. // Move to a different heap allocation in order to detect bugs.
  2397. const size_t cap = capacity();
  2398. resize(growth_left() > 0 ? cap : NextCapacity(cap));
  2399. }
  2400. auto target = find_first_non_full(common(), hash);
  2401. if (!rehash_for_bug_detection &&
  2402. Y_ABSL_PREDICT_FALSE(growth_left() == 0 &&
  2403. !IsDeleted(control()[target.offset]))) {
  2404. rehash_and_grow_if_necessary();
  2405. target = find_first_non_full(common(), hash);
  2406. }
  2407. common().set_size(common().size() + 1);
  2408. set_growth_left(growth_left() - IsEmpty(control()[target.offset]));
  2409. SetCtrl(common(), target.offset, H2(hash), sizeof(slot_type));
  2410. common().maybe_increment_generation_on_insert();
  2411. infoz().RecordInsert(hash, target.probe_length);
  2412. return target.offset;
  2413. }
  2414. // Constructs the value in the space pointed by the iterator. This only works
  2415. // after an unsuccessful find_or_prepare_insert() and before any other
  2416. // modifications happen in the raw_hash_set.
  2417. //
  2418. // PRECONDITION: i is an index returned from find_or_prepare_insert(k), where
  2419. // k is the key decomposed from `forward<Args>(args)...`, and the bool
  2420. // returned by find_or_prepare_insert(k) was true.
  2421. // POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...).
  2422. template <class... Args>
  2423. void emplace_at(size_t i, Args&&... args) {
  2424. PolicyTraits::construct(&alloc_ref(), slot_array() + i,
  2425. std::forward<Args>(args)...);
  2426. assert(PolicyTraits::apply(FindElement{*this}, *iterator_at(i)) ==
  2427. iterator_at(i) &&
  2428. "constructed value does not match the lookup key");
  2429. }
  2430. iterator iterator_at(size_t i) Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  2431. return {control() + i, slot_array() + i, common().generation_ptr()};
  2432. }
  2433. const_iterator iterator_at(size_t i) const Y_ABSL_ATTRIBUTE_LIFETIME_BOUND {
  2434. return {control() + i, slot_array() + i, common().generation_ptr()};
  2435. }
  2436. private:
  2437. friend struct RawHashSetTestOnlyAccess;
  2438. // The number of slots we can still fill without needing to rehash.
  2439. //
  2440. // This is stored separately due to tombstones: we do not include tombstones
  2441. // in the growth capacity, because we'd like to rehash when the table is
  2442. // otherwise filled with tombstones: otherwise, probe sequences might get
  2443. // unacceptably long without triggering a rehash. Callers can also force a
  2444. // rehash via the standard `rehash(0)`, which will recompute this value as a
  2445. // side-effect.
  2446. //
  2447. // See `CapacityToGrowth()`.
  2448. size_t growth_left() const { return common().growth_left(); }
  2449. void set_growth_left(size_t gl) { return common().set_growth_left(gl); }
  2450. // Prefetch the heap-allocated memory region to resolve potential TLB and
  2451. // cache misses. This is intended to overlap with execution of calculating the
  2452. // hash for a key.
  2453. void prefetch_heap_block() const {
  2454. #if Y_ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
  2455. __builtin_prefetch(control(), 0, 1);
  2456. #endif
  2457. }
  2458. CommonFields& common() { return settings_.template get<0>(); }
  2459. const CommonFields& common() const { return settings_.template get<0>(); }
  2460. ctrl_t* control() const { return common().control(); }
  2461. slot_type* slot_array() const {
  2462. return static_cast<slot_type*>(common().slot_array());
  2463. }
  2464. HashtablezInfoHandle& infoz() { return common().infoz(); }
  2465. hasher& hash_ref() { return settings_.template get<1>(); }
  2466. const hasher& hash_ref() const { return settings_.template get<1>(); }
  2467. key_equal& eq_ref() { return settings_.template get<2>(); }
  2468. const key_equal& eq_ref() const { return settings_.template get<2>(); }
  2469. allocator_type& alloc_ref() { return settings_.template get<3>(); }
  2470. const allocator_type& alloc_ref() const {
  2471. return settings_.template get<3>();
  2472. }
  2473. // Make type-specific functions for this type's PolicyFunctions struct.
  2474. static size_t hash_slot_fn(void* set, void* slot) {
  2475. auto* h = static_cast<raw_hash_set*>(set);
  2476. return PolicyTraits::apply(
  2477. HashElement{h->hash_ref()},
  2478. PolicyTraits::element(static_cast<slot_type*>(slot)));
  2479. }
  2480. static void transfer_slot_fn(void* set, void* dst, void* src) {
  2481. auto* h = static_cast<raw_hash_set*>(set);
  2482. PolicyTraits::transfer(&h->alloc_ref(), static_cast<slot_type*>(dst),
  2483. static_cast<slot_type*>(src));
  2484. }
  2485. // Note: dealloc_fn will only be used if we have a non-standard allocator.
  2486. static void dealloc_fn(CommonFields& common, const PolicyFunctions&) {
  2487. auto* set = reinterpret_cast<raw_hash_set*>(&common);
  2488. // Unpoison before returning the memory to the allocator.
  2489. SanitizerUnpoisonMemoryRegion(common.slot_array(),
  2490. sizeof(slot_type) * common.capacity());
  2491. Deallocate<BackingArrayAlignment(alignof(slot_type))>(
  2492. &set->alloc_ref(), common.backing_array_start(),
  2493. common.alloc_size(sizeof(slot_type), alignof(slot_type)));
  2494. }
  2495. static const PolicyFunctions& GetPolicyFunctions() {
  2496. static constexpr PolicyFunctions value = {
  2497. sizeof(slot_type),
  2498. &raw_hash_set::hash_slot_fn,
  2499. PolicyTraits::transfer_uses_memcpy()
  2500. ? TransferRelocatable<sizeof(slot_type)>
  2501. : &raw_hash_set::transfer_slot_fn,
  2502. (std::is_same<SlotAlloc, std::allocator<slot_type>>::value
  2503. ? &DeallocateStandard<alignof(slot_type)>
  2504. : &raw_hash_set::dealloc_fn),
  2505. };
  2506. return value;
  2507. }
  2508. // Bundle together CommonFields plus other objects which might be empty.
  2509. // CompressedTuple will ensure that sizeof is not affected by any of the empty
  2510. // fields that occur after CommonFields.
  2511. y_absl::container_internal::CompressedTuple<CommonFields, hasher, key_equal,
  2512. allocator_type>
  2513. settings_{CommonFields{}, hasher{}, key_equal{}, allocator_type{}};
  2514. };
  2515. // Erases all elements that satisfy the predicate `pred` from the container `c`.
  2516. template <typename P, typename H, typename E, typename A, typename Predicate>
  2517. typename raw_hash_set<P, H, E, A>::size_type EraseIf(
  2518. Predicate& pred, raw_hash_set<P, H, E, A>* c) {
  2519. const auto initial_size = c->size();
  2520. for (auto it = c->begin(), last = c->end(); it != last;) {
  2521. if (pred(*it)) {
  2522. c->erase(it++);
  2523. } else {
  2524. ++it;
  2525. }
  2526. }
  2527. return initial_size - c->size();
  2528. }
  2529. namespace hashtable_debug_internal {
  2530. template <typename Set>
  2531. struct HashtableDebugAccess<Set, y_absl::void_t<typename Set::raw_hash_set>> {
  2532. using Traits = typename Set::PolicyTraits;
  2533. using Slot = typename Traits::slot_type;
  2534. static size_t GetNumProbes(const Set& set,
  2535. const typename Set::key_type& key) {
  2536. size_t num_probes = 0;
  2537. size_t hash = set.hash_ref()(key);
  2538. auto seq = probe(set.common(), hash);
  2539. const ctrl_t* ctrl = set.control();
  2540. while (true) {
  2541. container_internal::Group g{ctrl + seq.offset()};
  2542. for (uint32_t i : g.Match(container_internal::H2(hash))) {
  2543. if (Traits::apply(
  2544. typename Set::template EqualElement<typename Set::key_type>{
  2545. key, set.eq_ref()},
  2546. Traits::element(set.slot_array() + seq.offset(i))))
  2547. return num_probes;
  2548. ++num_probes;
  2549. }
  2550. if (g.MaskEmpty()) return num_probes;
  2551. seq.next();
  2552. ++num_probes;
  2553. }
  2554. }
  2555. static size_t AllocatedByteSize(const Set& c) {
  2556. size_t capacity = c.capacity();
  2557. if (capacity == 0) return 0;
  2558. size_t m = AllocSize(capacity, sizeof(Slot), alignof(Slot));
  2559. size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
  2560. if (per_slot != ~size_t{}) {
  2561. m += per_slot * c.size();
  2562. } else {
  2563. const ctrl_t* ctrl = c.control();
  2564. for (size_t i = 0; i != capacity; ++i) {
  2565. if (container_internal::IsFull(ctrl[i])) {
  2566. m += Traits::space_used(c.slot_array() + i);
  2567. }
  2568. }
  2569. }
  2570. return m;
  2571. }
  2572. static size_t LowerBoundAllocatedByteSize(size_t size) {
  2573. size_t capacity = GrowthToLowerboundCapacity(size);
  2574. if (capacity == 0) return 0;
  2575. size_t m =
  2576. AllocSize(NormalizeCapacity(capacity), sizeof(Slot), alignof(Slot));
  2577. size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
  2578. if (per_slot != ~size_t{}) {
  2579. m += per_slot * size;
  2580. }
  2581. return m;
  2582. }
  2583. };
  2584. } // namespace hashtable_debug_internal
  2585. } // namespace container_internal
  2586. Y_ABSL_NAMESPACE_END
  2587. } // namespace y_absl
  2588. #undef Y_ABSL_SWISSTABLE_ENABLE_GENERATIONS
  2589. #endif // Y_ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_