hash.h 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029
  1. #pragma once
  2. #include "fwd.h"
  3. #include "mapfindptr.h"
  4. #include <util/memory/alloc.h>
  5. #include <util/system/type_name.h>
  6. #include <util/system/yassert.h>
  7. #include <util/str_stl.h>
  8. #include "yexception.h"
  9. #include "typetraits.h"
  10. #include "utility.h"
  11. #include <algorithm>
  12. #include <initializer_list>
  13. #include <memory>
  14. #include <tuple>
  15. #include <utility>
  16. #include <cstdlib>
  17. #include "hash_primes.h"
  18. struct TSelect1st {
  19. template <class TPair>
  20. inline const typename TPair::first_type& operator()(const TPair& x) const {
  21. return x.first;
  22. }
  23. };
  24. template <class Value>
  25. struct __yhashtable_node {
  26. /** If the first bit is not set, then this is a pointer to the next node in
  27. * the list of nodes for the current bucket. Otherwise this is a pointer of
  28. * type __yhashtable_node**, pointing back into the buckets array.
  29. *
  30. * This trick makes it possible to use only one node pointer in a hash table
  31. * iterator. */
  32. __yhashtable_node* next;
  33. /** Value stored in a node. */
  34. Value val;
  35. __yhashtable_node& operator=(const __yhashtable_node&) = delete;
  36. };
  37. template <class Value, class Key, class HashFcn,
  38. class ExtractKey, class EqualKey, class Alloc>
  39. class THashTable;
  40. template <class Key, class T, class HashFcn,
  41. class EqualKey, typename size_type_f>
  42. class sthash;
  43. template <class Value>
  44. struct __yhashtable_iterator;
  45. template <class Value>
  46. struct __yhashtable_const_iterator;
  47. template <class Value>
  48. struct __yhashtable_iterator {
  49. using iterator = __yhashtable_iterator<Value>;
  50. using const_iterator = __yhashtable_const_iterator<Value>;
  51. using node = __yhashtable_node<Value>;
  52. using iterator_category = std::forward_iterator_tag;
  53. using value_type = Value;
  54. using difference_type = ptrdiff_t;
  55. using size_type = size_t;
  56. using reference = Value&;
  57. using pointer = Value*;
  58. node* cur;
  59. explicit __yhashtable_iterator(node* n)
  60. : cur(n)
  61. {
  62. } /*y*/
  63. __yhashtable_iterator() = default;
  64. reference operator*() const {
  65. return cur->val;
  66. }
  67. pointer operator->() const {
  68. return &(operator*());
  69. }
  70. iterator& operator++();
  71. iterator operator++(int);
  72. bool operator==(const iterator& it) const {
  73. return cur == it.cur;
  74. }
  75. bool operator!=(const iterator& it) const {
  76. return cur != it.cur;
  77. }
  78. bool IsEnd() const {
  79. return !cur;
  80. }
  81. Y_FORCE_INLINE explicit operator bool() const noexcept {
  82. return cur != nullptr;
  83. }
  84. };
  85. template <class Value>
  86. struct __yhashtable_const_iterator {
  87. using iterator = __yhashtable_iterator<Value>;
  88. using const_iterator = __yhashtable_const_iterator<Value>;
  89. using node = __yhashtable_node<Value>;
  90. using iterator_category = std::forward_iterator_tag;
  91. using value_type = Value;
  92. using difference_type = ptrdiff_t;
  93. using size_type = size_t;
  94. using reference = const Value&;
  95. using pointer = const Value*;
  96. const node* cur;
  97. explicit __yhashtable_const_iterator(const node* n)
  98. : cur(n)
  99. {
  100. }
  101. __yhashtable_const_iterator() {
  102. }
  103. __yhashtable_const_iterator(const iterator& it)
  104. : cur(it.cur)
  105. {
  106. }
  107. reference operator*() const {
  108. return cur->val;
  109. }
  110. pointer operator->() const {
  111. return &(operator*());
  112. }
  113. const_iterator& operator++();
  114. const_iterator operator++(int);
  115. bool operator==(const const_iterator& it) const {
  116. return cur == it.cur;
  117. }
  118. bool operator!=(const const_iterator& it) const {
  119. return cur != it.cur;
  120. }
  121. bool IsEnd() const {
  122. return !cur;
  123. }
  124. Y_FORCE_INLINE explicit operator bool() const noexcept {
  125. return cur != nullptr;
  126. }
  127. };
  128. /**
  129. * This class saves some space in allocator-based containers for the most common
  130. * use case of empty allocators. This is achieved thanks to the application of
  131. * empty base class optimization (aka EBCO).
  132. */
  133. template <class Alloc>
  134. class _allocator_base: private Alloc {
  135. public:
  136. _allocator_base(const Alloc& other)
  137. : Alloc(other)
  138. {
  139. }
  140. Alloc& _get_alloc() {
  141. return static_cast<Alloc&>(*this);
  142. }
  143. const Alloc& _get_alloc() const {
  144. return static_cast<const Alloc&>(*this);
  145. }
  146. void _set_alloc(const Alloc& allocator) {
  147. _get_alloc() = allocator;
  148. }
  149. void swap(_allocator_base& other) {
  150. DoSwap(_get_alloc(), other._get_alloc());
  151. }
  152. };
  153. /**
  154. * Wrapper for an array of THashTable buckets.
  155. *
  156. * Is better than vector for this particular use case. Main differences:
  157. * - Occupies one less word on stack.
  158. * - Doesn't even try to initialize its elements. It is THashTable's responsibility.
  159. * - Presents a better interface in relation to THashTable's marker element trick.
  160. *
  161. * Internally this class is just a pointer-size pair, and the data on the heap
  162. * has the following structure:
  163. *
  164. * +----------+----------------------+----------+-------------------------+
  165. * | raw_size | elements ... | marker | unused space [optional] |
  166. * +----------+----------------------+----------+-------------------------+
  167. * ^ ^
  168. * | |
  169. * Data points here end() points here
  170. *
  171. * `raw_size` stores the size of the allocated memory block. It is used to
  172. * support resizing without reallocation.
  173. *
  174. * `marker` is a special marker element that is set by the THashTable that is
  175. * then used in iterator implementation to know when the end is reached.
  176. *
  177. * Unused space at the end of the memory block may not be present.
  178. */
  179. template <class T, class Alloc>
  180. class _yhashtable_buckets: private _allocator_base<Alloc> {
  181. using base_type = _allocator_base<Alloc>;
  182. static_assert(sizeof(T) == sizeof(size_t), "T is expected to be the same size as size_t.");
  183. public:
  184. using allocator_type = Alloc;
  185. using value_type = T;
  186. using pointer = T*;
  187. using const_pointer = const T*;
  188. using reference = T&;
  189. using const_reference = const T&;
  190. using iterator = pointer;
  191. using const_iterator = const_pointer;
  192. using size_type = size_t;
  193. using difference_type = ptrdiff_t;
  194. using TBucketDivisor = ::NPrivate::THashDivisor;
  195. _yhashtable_buckets(const Alloc& other)
  196. : base_type(other)
  197. , Data(nullptr)
  198. , Size()
  199. {
  200. }
  201. ~_yhashtable_buckets() {
  202. Y_ASSERT(!Data);
  203. }
  204. void initialize_dynamic(TBucketDivisor size) {
  205. Y_ASSERT(!Data);
  206. Data = this->_get_alloc().allocate(size() + 2) + 1;
  207. Size = size;
  208. *reinterpret_cast<size_type*>(Data - 1) = size() + 2;
  209. }
  210. void deinitialize_dynamic() {
  211. Y_ASSERT(Data);
  212. this->_get_alloc().deallocate(Data - 1, *reinterpret_cast<size_type*>(Data - 1));
  213. Data = pointer();
  214. Size = TBucketDivisor();
  215. }
  216. void initialize_static(pointer data, TBucketDivisor size) {
  217. Y_ASSERT(!Data && data && size() >= 1);
  218. Data = data;
  219. Size = size;
  220. }
  221. void deinitialize_static() {
  222. Y_ASSERT(Data);
  223. Data = pointer();
  224. Size = TBucketDivisor();
  225. }
  226. void resize_noallocate(TBucketDivisor size) {
  227. Y_ASSERT(size() <= capacity());
  228. Size = size;
  229. }
  230. iterator begin() {
  231. return Data;
  232. }
  233. const_iterator begin() const {
  234. return Data;
  235. }
  236. iterator end() {
  237. return Data + Size();
  238. }
  239. const_iterator end() const {
  240. return Data + Size();
  241. }
  242. pointer data() {
  243. return Data;
  244. }
  245. const_pointer data() const {
  246. return Data;
  247. }
  248. size_type size() const {
  249. return Size();
  250. }
  251. size_type capacity() const {
  252. return *reinterpret_cast<size_type*>(Data - 1);
  253. }
  254. TBucketDivisor ExtSize() const {
  255. return Size;
  256. }
  257. int BucketDivisorHint() const {
  258. return +Size.Hint;
  259. }
  260. allocator_type get_allocator() const {
  261. return this->_get_alloc();
  262. }
  263. const_reference operator[](size_type index) const {
  264. Y_ASSERT(index <= Size());
  265. return *(Data + index);
  266. }
  267. reference operator[](size_type index) {
  268. Y_ASSERT(index <= Size());
  269. return *(Data + index);
  270. }
  271. void swap(_yhashtable_buckets& other) {
  272. base_type::swap(other);
  273. DoSwap(Data, other.Data);
  274. DoSwap(Size, other.Size);
  275. }
  276. private:
  277. /** Pointer to the first element of the buckets array. */
  278. pointer Data;
  279. /** Size of the buckets array. Doesn't take the marker element at the end into account. */
  280. TBucketDivisor Size;
  281. };
  282. /**
  283. * This class saves one word in THashTable for the most common use case of empty
  284. * functors. The exact implementation picks a specialization with storage allocated
  285. * for the functors if those are non-empty, and another specialization that creates
  286. * functors on the fly if they are empty. It is expected that empty functors have
  287. * trivial constructors.
  288. *
  289. * Note that this is basically the only way to do it portably. Another option is
  290. * multiple inheritance from empty functors, but MSVC's empty base class
  291. * optimization chokes up on multiple empty bases, and we're already using
  292. * EBCO in _allocator_base.
  293. *
  294. * Note that there are no specializations for the case when only one or two
  295. * of the functors are empty as this is a case that's just way too rare.
  296. */
  297. template <class HashFcn, class ExtractKey, class EqualKey, class Alloc, bool IsEmpty = std::is_empty<HashFcn>::value&& std::is_empty<ExtractKey>::value&& std::is_empty<EqualKey>::value>
  298. class _yhashtable_base: public _allocator_base<Alloc> {
  299. using base_type = _allocator_base<Alloc>;
  300. public:
  301. _yhashtable_base(const HashFcn& hash, const ExtractKey& extract, const EqualKey& equals, const Alloc& alloc)
  302. : base_type(alloc)
  303. , hash_(hash)
  304. , extract_(extract)
  305. , equals_(equals)
  306. {
  307. }
  308. const EqualKey& _get_key_eq() const {
  309. return equals_;
  310. }
  311. EqualKey& _get_key_eq() {
  312. return equals_;
  313. }
  314. void _set_key_eq(const EqualKey& equals) {
  315. this->equals_ = equals;
  316. }
  317. const ExtractKey& _get_key_extract() const {
  318. return extract_;
  319. }
  320. ExtractKey& _get_key_extract() {
  321. return extract_;
  322. }
  323. void _set_key_extract(const ExtractKey& extract) {
  324. this->extract_ = extract;
  325. }
  326. const HashFcn& _get_hash_fun() const {
  327. return hash_;
  328. }
  329. HashFcn& _get_hash_fun() {
  330. return hash_;
  331. }
  332. void _set_hash_fun(const HashFcn& hash) {
  333. this->hash_ = hash;
  334. }
  335. void swap(_yhashtable_base& other) {
  336. base_type::swap(other);
  337. DoSwap(equals_, other.equals_);
  338. DoSwap(extract_, other.extract_);
  339. DoSwap(hash_, other.hash_);
  340. }
  341. private:
  342. HashFcn hash_;
  343. ExtractKey extract_;
  344. EqualKey equals_;
  345. };
  346. template <class HashFcn, class ExtractKey, class EqualKey, class Alloc>
  347. class _yhashtable_base<HashFcn, ExtractKey, EqualKey, Alloc, true>: public _allocator_base<Alloc> {
  348. using base_type = _allocator_base<Alloc>;
  349. public:
  350. _yhashtable_base(const HashFcn&, const ExtractKey&, const EqualKey&, const Alloc& alloc)
  351. : base_type(alloc)
  352. {
  353. }
  354. EqualKey _get_key_eq() const {
  355. return EqualKey();
  356. }
  357. void _set_key_eq(const EqualKey&) {
  358. }
  359. ExtractKey _get_key_extract() const {
  360. return ExtractKey();
  361. }
  362. void _set_key_extract(const ExtractKey&) {
  363. }
  364. HashFcn _get_hash_fun() const {
  365. return HashFcn();
  366. }
  367. void _set_hash_fun(const HashFcn&) {
  368. }
  369. void swap(_yhashtable_base& other) {
  370. base_type::swap(other);
  371. }
  372. };
  373. template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
  374. struct _yhashtable_traits {
  375. using node = __yhashtable_node<Value>;
  376. using node_allocator_type = TReboundAllocator<Alloc, node>;
  377. using nodep_allocator_type = TReboundAllocator<Alloc, node*>;
  378. using base_type = _yhashtable_base<HashFcn, ExtractKey, EqualKey, node_allocator_type>;
  379. };
  380. extern const void* const _yhashtable_empty_data[];
  381. template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
  382. class THashTable: private _yhashtable_traits<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::base_type {
  383. using traits_type = _yhashtable_traits<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
  384. using base_type = typename traits_type::base_type;
  385. using node = typename traits_type::node;
  386. using nodep_allocator_type = typename traits_type::nodep_allocator_type;
  387. using buckets_type = _yhashtable_buckets<node*, nodep_allocator_type>;
  388. using TBucketDivisor = ::NPrivate::THashDivisor;
  389. public:
  390. using key_type = Key;
  391. using value_type = Value;
  392. using hasher = HashFcn;
  393. using key_equal = EqualKey;
  394. using key_extract = ExtractKey;
  395. using allocator_type = Alloc;
  396. using node_allocator_type = typename traits_type::node_allocator_type;
  397. using size_type = size_t;
  398. using difference_type = ptrdiff_t;
  399. using pointer = value_type*;
  400. using const_pointer = const value_type*;
  401. using reference = value_type&;
  402. using const_reference = const value_type&;
  403. node_allocator_type& GetNodeAllocator() {
  404. return this->_get_alloc();
  405. }
  406. const node_allocator_type& GetNodeAllocator() const {
  407. return this->_get_alloc();
  408. }
  409. key_equal key_eq() const {
  410. return this->_get_key_eq();
  411. }
  412. hasher hash_function() const {
  413. return this->_get_hash_fun();
  414. }
  415. private:
  416. template <class KeyL, class KeyR>
  417. bool equals(const KeyL& l, const KeyR& r) const {
  418. return this->_get_key_eq()(l, r);
  419. }
  420. /* This method is templated to postpone instantiation of key extraction functor. */
  421. template <class ValueL>
  422. auto get_key(const ValueL& value) const -> decltype(ExtractKey()(value)) {
  423. return this->_get_key_extract()(value);
  424. }
  425. node* get_node() {
  426. node* result = this->_get_alloc().allocate(1);
  427. Y_ASSERT((reinterpret_cast<uintptr_t>(result) & 1) == 0); /* We're using the last bit of the node pointer. */
  428. return result;
  429. }
  430. void put_node(node* p) {
  431. this->_get_alloc().deallocate(p, 1);
  432. }
  433. buckets_type buckets;
  434. size_type num_elements;
  435. public:
  436. using iterator = __yhashtable_iterator<Value>;
  437. using const_iterator = __yhashtable_const_iterator<Value>;
  438. using insert_ctx = node**;
  439. friend struct __yhashtable_iterator<Value>;
  440. friend struct __yhashtable_const_iterator<Value>;
  441. public:
  442. THashTable()
  443. : base_type(HashFcn(), ExtractKey(), EqualKey(), node_allocator_type())
  444. , buckets(nodep_allocator_type())
  445. , num_elements(0)
  446. {
  447. initialize_buckets(buckets, 0);
  448. }
  449. THashTable(size_type n, const HashFcn& hf, const EqualKey& eql, const ExtractKey& ext)
  450. : base_type(hf, ext, eql, node_allocator_type())
  451. , buckets(nodep_allocator_type())
  452. , num_elements(0)
  453. {
  454. initialize_buckets(buckets, n);
  455. }
  456. THashTable(size_type n, const HashFcn& hf, const EqualKey& eql)
  457. : base_type(hf, ExtractKey(), eql, node_allocator_type())
  458. , buckets(nodep_allocator_type())
  459. , num_elements(0)
  460. {
  461. initialize_buckets(buckets, n);
  462. }
  463. template <class TAllocParam>
  464. THashTable(size_type n, const HashFcn& hf, const EqualKey& eql, TAllocParam* allocParam)
  465. : base_type(hf, ExtractKey(), eql, allocParam)
  466. , buckets(allocParam)
  467. , num_elements(0)
  468. {
  469. initialize_buckets(buckets, n);
  470. }
  471. THashTable(const THashTable& ht)
  472. : base_type(ht._get_hash_fun(), ht._get_key_extract(), ht._get_key_eq(), ht._get_alloc())
  473. , buckets(ht.buckets.get_allocator())
  474. , num_elements(0)
  475. {
  476. if (ht.empty()) {
  477. initialize_buckets(buckets, 0);
  478. } else {
  479. initialize_buckets_dynamic(buckets, ht.buckets.ExtSize());
  480. copy_from_dynamic(ht);
  481. }
  482. }
  483. THashTable(THashTable&& ht) noexcept
  484. : base_type(ht._get_hash_fun(), ht._get_key_extract(), ht._get_key_eq(), ht._get_alloc())
  485. , buckets(ht.buckets.get_allocator())
  486. , num_elements(0)
  487. {
  488. initialize_buckets(buckets, 0);
  489. this->swap(ht);
  490. }
  491. THashTable& operator=(const THashTable& ht) {
  492. if (&ht != this) {
  493. basic_clear();
  494. this->_set_hash_fun(ht._get_hash_fun());
  495. this->_set_key_eq(ht._get_key_eq());
  496. this->_set_key_extract(ht._get_key_extract());
  497. /* We don't copy allocator for a reason. */
  498. if (ht.empty()) {
  499. /* Some of the old code in Arcadia works around the behavior in
  500. * clear() by invoking operator= with empty hash as an argument.
  501. * It's expected that this will deallocate the buckets array, so
  502. * this is what we have to do here. */
  503. deinitialize_buckets(buckets);
  504. initialize_buckets(buckets, 0);
  505. } else {
  506. if (buckets.capacity() > ht.buckets.size()) {
  507. buckets.resize_noallocate(ht.buckets.ExtSize());
  508. } else {
  509. deinitialize_buckets(buckets);
  510. initialize_buckets_dynamic(buckets, ht.buckets.ExtSize());
  511. }
  512. copy_from_dynamic(ht);
  513. }
  514. }
  515. return *this;
  516. }
  517. THashTable& operator=(THashTable&& ht) noexcept {
  518. basic_clear();
  519. swap(ht);
  520. return *this;
  521. }
  522. ~THashTable() {
  523. basic_clear();
  524. deinitialize_buckets(buckets);
  525. }
  526. size_type size() const noexcept {
  527. return num_elements;
  528. }
  529. size_type max_size() const noexcept {
  530. return size_type(-1);
  531. }
  532. Y_PURE_FUNCTION bool empty() const noexcept {
  533. return size() == 0;
  534. }
  535. void swap(THashTable& ht) {
  536. base_type::swap(ht);
  537. buckets.swap(ht.buckets);
  538. DoSwap(num_elements, ht.num_elements);
  539. }
  540. iterator begin() {
  541. for (size_type n = 0; n < buckets.size(); ++n) /*y*/
  542. if (buckets[n])
  543. return iterator(buckets[n]); /*y*/
  544. return end();
  545. }
  546. iterator end() {
  547. return iterator(nullptr);
  548. } /*y*/
  549. const_iterator begin() const {
  550. for (size_type n = 0; n < buckets.size(); ++n) /*y*/
  551. if (buckets[n])
  552. return const_iterator(buckets[n]); /*y*/
  553. return end();
  554. }
  555. const_iterator end() const {
  556. return const_iterator(nullptr);
  557. } /*y*/
  558. public:
  559. size_type bucket_count() const {
  560. return buckets.size();
  561. } /*y*/
  562. size_type bucket_size(size_type bucket) const {
  563. size_type result = 0;
  564. if (const node* cur = buckets[bucket])
  565. for (; !((uintptr_t)cur & 1); cur = cur->next)
  566. result += 1;
  567. return result;
  568. }
  569. template <class OtherValue>
  570. std::pair<iterator, bool> insert_unique(const OtherValue& obj) {
  571. reserve(num_elements + 1);
  572. return insert_unique_noresize(obj);
  573. }
  574. template <class OtherValue>
  575. iterator insert_equal(const OtherValue& obj) {
  576. reserve(num_elements + 1);
  577. return emplace_equal_noresize(obj);
  578. }
  579. template <typename... Args>
  580. iterator emplace_equal(Args&&... args) {
  581. reserve(num_elements + 1);
  582. return emplace_equal_noresize(std::forward<Args>(args)...);
  583. }
  584. template <class OtherValue>
  585. iterator insert_direct(const OtherValue& obj, insert_ctx ins) {
  586. return emplace_direct(ins, obj);
  587. }
  588. template <typename... Args>
  589. iterator emplace_direct(insert_ctx ins, Args&&... args) {
  590. bool resized = reserve(num_elements + 1);
  591. node* tmp = new_node(std::forward<Args>(args)...);
  592. if (resized) {
  593. find_i(get_key(tmp->val), ins);
  594. }
  595. tmp->next = *ins ? *ins : (node*)((uintptr_t)(ins + 1) | 1);
  596. *ins = tmp;
  597. ++num_elements;
  598. return iterator(tmp);
  599. }
  600. template <typename... Args>
  601. std::pair<iterator, bool> emplace_unique(Args&&... args) {
  602. reserve(num_elements + 1);
  603. return emplace_unique_noresize(std::forward<Args>(args)...);
  604. }
  605. template <typename... Args>
  606. std::pair<iterator, bool> emplace_unique_noresize(Args&&... args);
  607. template <class OtherValue>
  608. std::pair<iterator, bool> insert_unique_noresize(const OtherValue& obj);
  609. template <typename... Args>
  610. iterator emplace_equal_noresize(Args&&... args);
  611. template <class InputIterator>
  612. void insert_unique(InputIterator f, InputIterator l) {
  613. insert_unique(f, l, typename std::iterator_traits<InputIterator>::iterator_category());
  614. }
  615. template <class InputIterator>
  616. void insert_equal(InputIterator f, InputIterator l) {
  617. insert_equal(f, l, typename std::iterator_traits<InputIterator>::iterator_category());
  618. }
  619. template <class InputIterator>
  620. void insert_unique(InputIterator f, InputIterator l, std::input_iterator_tag) {
  621. for (; f != l; ++f)
  622. insert_unique(*f);
  623. }
  624. template <class InputIterator>
  625. void insert_equal(InputIterator f, InputIterator l, std::input_iterator_tag) {
  626. for (; f != l; ++f)
  627. insert_equal(*f);
  628. }
  629. template <class ForwardIterator>
  630. void insert_unique(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) {
  631. difference_type n = std::distance(f, l);
  632. reserve(num_elements + n);
  633. for (; n > 0; --n, ++f)
  634. insert_unique_noresize(*f);
  635. }
  636. template <class ForwardIterator>
  637. void insert_equal(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) {
  638. difference_type n = std::distance(f, l);
  639. reserve(num_elements + n);
  640. for (; n > 0; --n, ++f)
  641. emplace_equal_noresize(*f);
  642. }
  643. template <class OtherValue>
  644. reference find_or_insert(const OtherValue& v);
  645. template <class OtherKey>
  646. iterator find(const OtherKey& key) {
  647. size_type n = bkt_num_key(key);
  648. node* first;
  649. for (first = buckets[n];
  650. first && !equals(get_key(first->val), key);
  651. first = ((uintptr_t)first->next & 1) ? nullptr : first->next) /*y*/
  652. {
  653. }
  654. return iterator(first); /*y*/
  655. }
  656. template <class OtherKey>
  657. const_iterator find(const OtherKey& key) const {
  658. size_type n = bkt_num_key(key);
  659. const node* first;
  660. for (first = buckets[n];
  661. first && !equals(get_key(first->val), key);
  662. first = ((uintptr_t)first->next & 1) ? nullptr : first->next) /*y*/
  663. {
  664. }
  665. return const_iterator(first); /*y*/
  666. }
  667. template <class OtherKey>
  668. iterator find_i(const OtherKey& key, insert_ctx& ins);
  669. template <class OtherKey>
  670. size_type count(const OtherKey& key) const {
  671. const size_type n = bkt_num_key(key);
  672. size_type result = 0;
  673. if (const node* cur = buckets[n])
  674. for (; !((uintptr_t)cur & 1); cur = cur->next)
  675. if (equals(get_key(cur->val), key))
  676. ++result;
  677. return result;
  678. }
  679. template <class OtherKey>
  680. std::pair<iterator, iterator> equal_range(const OtherKey& key);
  681. template <class OtherKey>
  682. std::pair<const_iterator, const_iterator> equal_range(const OtherKey& key) const;
  683. template <class OtherKey>
  684. size_type erase(const OtherKey& key);
  685. template <class OtherKey>
  686. size_type erase_one(const OtherKey& key);
  687. // void (instead of iterator) is intended, see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2023.pdf
  688. void erase(const iterator& it);
  689. void erase(iterator first, iterator last);
  690. void erase(const const_iterator& it);
  691. void erase(const_iterator first, const_iterator last);
  692. bool reserve(size_type num_elements_hint);
  693. void basic_clear();
  694. /**
  695. * Clears the hashtable without deallocating the nodes.
  696. *
  697. * This might come in handy with non-standard allocators, e.g. a pool
  698. * allocator with a pool that is then cleared manually, thus releasing all
  699. * the nodes at once.
  700. */
  701. void release_nodes() {
  702. if (empty())
  703. return; /* Need this check because empty buckets may reside in read-only memory. */
  704. clear_buckets(buckets);
  705. num_elements = 0;
  706. }
  707. // implemented in save_stl.h
  708. template <class KeySaver>
  709. int save_for_st(IOutputStream* stream, KeySaver& ks, sthash<int, int, THash<int>, TEqualTo<int>, typename KeySaver::TSizeType>* stHash = nullptr) const;
  710. void clear(size_type downsize) {
  711. basic_clear();
  712. if (downsize < buckets.size()) {
  713. const TBucketDivisor newSize = HashBucketCountExt(downsize);
  714. if (newSize() < buckets.size()) {
  715. Y_ASSERT(newSize() >= 7); /* We cannot downsize static buckets. */
  716. buckets.resize_noallocate(newSize);
  717. }
  718. }
  719. }
  720. /**
  721. * Clears the hashtable and tries to reasonably downsize it. Note that
  722. * downsizing is mainly for the following use case:
  723. *
  724. * THashTable hash;
  725. * for(...) {
  726. * if (someCond())
  727. * hash.clear();
  728. * hash.insert(...);
  729. * }
  730. *
  731. * Here if at some point `hash` gets really big, then all the following calls
  732. * to `clear` become really slow as they have to iterate through all the the
  733. * empty buckets. This is worked around by squeezing the buckets array a little
  734. * bit with every `clear` call.
  735. *
  736. * Alternatively, the user can call `basic_clear`, which doesn't do the
  737. * downsizing.
  738. */
  739. void clear() {
  740. if (num_elements)
  741. clear((num_elements * 2 + buckets.size()) / 3);
  742. }
  743. private:
  744. static void initialize_buckets(buckets_type& buckets, size_type sizeHint) {
  745. if (sizeHint == 0) {
  746. buckets.initialize_static(reinterpret_cast<node**>(const_cast<void**>(_yhashtable_empty_data)) + 1, TBucketDivisor::One());
  747. } else {
  748. TBucketDivisor size = HashBucketCountExt(sizeHint);
  749. Y_ASSERT(size() >= 7);
  750. initialize_buckets_dynamic(buckets, size);
  751. }
  752. }
  753. static void initialize_buckets_dynamic(buckets_type& buckets, TBucketDivisor size) {
  754. buckets.initialize_dynamic(size);
  755. memset(buckets.data(), 0, size() * sizeof(*buckets.data()));
  756. buckets[size()] = (node*)1;
  757. }
  758. static void deinitialize_buckets(buckets_type& buckets) {
  759. if (buckets.size() == 1) {
  760. buckets.deinitialize_static();
  761. } else {
  762. buckets.deinitialize_dynamic();
  763. }
  764. }
  765. static void clear_buckets(buckets_type& buckets) {
  766. memset(buckets.data(), 0, buckets.size() * sizeof(*buckets.data()));
  767. }
  768. template <class OtherKey>
  769. size_type bkt_num_key(const OtherKey& key) const {
  770. return bkt_num_key(key, buckets.ExtSize());
  771. }
  772. template <class OtherValue>
  773. size_type bkt_num(const OtherValue& obj) const {
  774. return bkt_num_key(get_key(obj));
  775. }
  776. template <class OtherKey>
  777. size_type bkt_num_key(const OtherKey& key, TBucketDivisor n) const {
  778. const size_type bucket = n.Remainder(this->_get_hash_fun()(key));
  779. Y_ASSERT((0 <= bucket) && (bucket < n()));
  780. return bucket;
  781. }
  782. template <class OtherValue>
  783. size_type bkt_num(const OtherValue& obj, TBucketDivisor n) const {
  784. return bkt_num_key(get_key(obj), n);
  785. }
  786. template <typename... Args>
  787. node* new_node(Args&&... val) {
  788. node* n = get_node();
  789. n->next = (node*)1; /*y*/ // just for a case
  790. try {
  791. new (static_cast<void*>(&n->val)) Value(std::forward<Args>(val)...);
  792. } catch (...) {
  793. put_node(n);
  794. throw;
  795. }
  796. return n;
  797. }
  798. void delete_node(node* n) {
  799. n->val.~Value();
  800. //n->next = (node*) 0xDeadBeeful;
  801. put_node(n);
  802. }
  803. void erase_bucket(const size_type n, node* first, node* last);
  804. void erase_bucket(const size_type n, node* last);
  805. void copy_from_dynamic(const THashTable& ht);
  806. };
  807. template <class V>
  808. __yhashtable_iterator<V>& __yhashtable_iterator<V>::operator++() {
  809. Y_ASSERT(cur);
  810. cur = cur->next;
  811. if ((uintptr_t)cur & 1) {
  812. node** bucket = (node**)((uintptr_t)cur & ~1);
  813. while (*bucket == nullptr)
  814. ++bucket;
  815. Y_ASSERT(*bucket != nullptr);
  816. cur = (node*)((uintptr_t)*bucket & ~1);
  817. }
  818. return *this;
  819. }
  820. template <class V>
  821. inline __yhashtable_iterator<V> __yhashtable_iterator<V>::operator++(int) {
  822. iterator tmp = *this;
  823. ++*this;
  824. return tmp;
  825. }
  826. template <class V>
  827. __yhashtable_const_iterator<V>& __yhashtable_const_iterator<V>::operator++() {
  828. Y_ASSERT(cur);
  829. cur = cur->next;
  830. if ((uintptr_t)cur & 1) {
  831. node** bucket = (node**)((uintptr_t)cur & ~1);
  832. while (*bucket == nullptr)
  833. ++bucket;
  834. Y_ASSERT(*bucket != nullptr);
  835. cur = (node*)((uintptr_t)*bucket & ~1);
  836. }
  837. return *this;
  838. }
  839. template <class V>
  840. inline __yhashtable_const_iterator<V> __yhashtable_const_iterator<V>::operator++(int) {
  841. const_iterator tmp = *this;
  842. ++*this;
  843. return tmp;
  844. }
  845. template <class V, class K, class HF, class Ex, class Eq, class A>
  846. template <typename... Args>
  847. std::pair<typename THashTable<V, K, HF, Ex, Eq, A>::iterator, bool> THashTable<V, K, HF, Ex, Eq, A>::emplace_unique_noresize(Args&&... args) {
  848. auto deleter = [&](node* tmp) { delete_node(tmp); };
  849. node* tmp = new_node(std::forward<Args>(args)...);
  850. std::unique_ptr<node, decltype(deleter)> guard(tmp, deleter);
  851. const size_type n = bkt_num(tmp->val);
  852. node* first = buckets[n];
  853. if (first) /*y*/
  854. for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
  855. if (equals(get_key(cur->val), get_key(tmp->val)))
  856. return std::pair<iterator, bool>(iterator(cur), false); /*y*/
  857. guard.release();
  858. tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
  859. buckets[n] = tmp;
  860. ++num_elements;
  861. return std::pair<iterator, bool>(iterator(tmp), true); /*y*/
  862. }
  863. template <class V, class K, class HF, class Ex, class Eq, class A>
  864. template <class OtherValue>
  865. std::pair<typename THashTable<V, K, HF, Ex, Eq, A>::iterator, bool> THashTable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const OtherValue& obj) {
  866. const size_type n = bkt_num(obj);
  867. node* first = buckets[n];
  868. if (first) /*y*/
  869. for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
  870. if (equals(get_key(cur->val), get_key(obj)))
  871. return std::pair<iterator, bool>(iterator(cur), false); /*y*/
  872. node* tmp = new_node(obj);
  873. tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
  874. buckets[n] = tmp;
  875. ++num_elements;
  876. return std::pair<iterator, bool>(iterator(tmp), true); /*y*/
  877. }
  878. template <class V, class K, class HF, class Ex, class Eq, class A>
  879. template <typename... Args>
  880. __yhashtable_iterator<V> THashTable<V, K, HF, Ex, Eq, A>::emplace_equal_noresize(Args&&... args) {
  881. auto deleter = [&](node* tmp) { delete_node(tmp); };
  882. node* tmp = new_node(std::forward<Args>(args)...);
  883. std::unique_ptr<node, decltype(deleter)> guard(tmp, deleter);
  884. const size_type n = bkt_num(tmp->val);
  885. node* first = buckets[n];
  886. if (first) /*y*/
  887. for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
  888. if (equals(get_key(cur->val), get_key(tmp->val))) {
  889. guard.release();
  890. tmp->next = cur->next;
  891. cur->next = tmp;
  892. ++num_elements;
  893. return iterator(tmp); /*y*/
  894. }
  895. guard.release();
  896. tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
  897. buckets[n] = tmp;
  898. ++num_elements;
  899. return iterator(tmp); /*y*/
  900. }
  901. template <class V, class K, class HF, class Ex, class Eq, class A>
  902. template <class OtherValue>
  903. typename THashTable<V, K, HF, Ex, Eq, A>::reference THashTable<V, K, HF, Ex, Eq, A>::find_or_insert(const OtherValue& v) {
  904. reserve(num_elements + 1);
  905. size_type n = bkt_num_key(get_key(v));
  906. node* first = buckets[n];
  907. if (first) /*y*/
  908. for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
  909. if (equals(get_key(cur->val), get_key(v)))
  910. return cur->val;
  911. node* tmp = new_node(v);
  912. tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
  913. buckets[n] = tmp;
  914. ++num_elements;
  915. return tmp->val;
  916. }
  917. template <class V, class K, class HF, class Ex, class Eq, class A>
  918. template <class OtherKey>
  919. __yhashtable_iterator<V> THashTable<V, K, HF, Ex, Eq, A>::find_i(const OtherKey& key, insert_ctx& ins) {
  920. size_type n = bkt_num_key(key);
  921. ins = &buckets[n];
  922. node* first = buckets[n];
  923. if (first) /*y*/
  924. for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
  925. if (equals(get_key(cur->val), key))
  926. return iterator(cur); /*y*/
  927. return end();
  928. }
  929. template <class V, class K, class HF, class Ex, class Eq, class A>
  930. template <class OtherKey>
  931. std::pair<__yhashtable_iterator<V>, __yhashtable_iterator<V>> THashTable<V, K, HF, Ex, Eq, A>::equal_range(const OtherKey& key) {
  932. using pii = std::pair<iterator, iterator>;
  933. const size_type n = bkt_num_key(key);
  934. node* first = buckets[n];
  935. if (first) /*y*/
  936. for (; !((uintptr_t)first & 1); first = first->next) { /*y*/
  937. if (equals(get_key(first->val), key)) {
  938. for (node* cur = first->next; !((uintptr_t)cur & 1); cur = cur->next)
  939. if (!equals(get_key(cur->val), key))
  940. return pii(iterator(first), iterator(cur)); /*y*/
  941. for (size_type m = n + 1; m < buckets.size(); ++m) /*y*/
  942. if (buckets[m])
  943. return pii(iterator(first), /*y*/
  944. iterator(buckets[m])); /*y*/
  945. return pii(iterator(first), end()); /*y*/
  946. }
  947. }
  948. return pii(end(), end());
  949. }
  950. template <class V, class K, class HF, class Ex, class Eq, class A>
  951. template <class OtherKey>
  952. std::pair<__yhashtable_const_iterator<V>, __yhashtable_const_iterator<V>> THashTable<V, K, HF, Ex, Eq, A>::equal_range(const OtherKey& key) const {
  953. using pii = std::pair<const_iterator, const_iterator>;
  954. const size_type n = bkt_num_key(key);
  955. const node* first = buckets[n];
  956. if (first) /*y*/
  957. for (; !((uintptr_t)first & 1); first = first->next) { /*y*/
  958. if (equals(get_key(first->val), key)) {
  959. for (const node* cur = first->next; !((uintptr_t)cur & 1); cur = cur->next)
  960. if (!equals(get_key(cur->val), key))
  961. return pii(const_iterator(first), /*y*/
  962. const_iterator(cur)); /*y*/
  963. for (size_type m = n + 1; m < buckets.size(); ++m) /*y*/
  964. if (buckets[m])
  965. return pii(const_iterator(first /*y*/),
  966. const_iterator(buckets[m] /*y*/));
  967. return pii(const_iterator(first /*y*/), end());
  968. }
  969. }
  970. return pii(end(), end());
  971. }
  972. template <class V, class K, class HF, class Ex, class Eq, class A>
  973. template <class OtherKey>
  974. typename THashTable<V, K, HF, Ex, Eq, A>::size_type THashTable<V, K, HF, Ex, Eq, A>::erase(const OtherKey& key) {
  975. const size_type n = bkt_num_key(key);
  976. node* first = buckets[n];
  977. size_type erased = 0;
  978. if (first) {
  979. node* cur = first;
  980. node* next = cur->next;
  981. while (!((uintptr_t)next & 1)) { /*y*/
  982. if (equals(get_key(next->val), key)) {
  983. cur->next = next->next;
  984. ++erased;
  985. --num_elements;
  986. delete_node(next);
  987. next = cur->next;
  988. } else {
  989. cur = next;
  990. next = cur->next;
  991. }
  992. }
  993. if (equals(get_key(first->val), key)) {
  994. buckets[n] = ((uintptr_t)first->next & 1) ? nullptr : first->next; /*y*/
  995. ++erased;
  996. --num_elements;
  997. delete_node(first);
  998. }
  999. }
  1000. return erased;
  1001. }
  1002. template <class V, class K, class HF, class Ex, class Eq, class A>
  1003. template <class OtherKey>
  1004. typename THashTable<V, K, HF, Ex, Eq, A>::size_type THashTable<V, K, HF, Ex, Eq, A>::erase_one(const OtherKey& key) {
  1005. const size_type n = bkt_num_key(key);
  1006. node* first = buckets[n];
  1007. if (first) {
  1008. node* cur = first;
  1009. node* next = cur->next;
  1010. while (!((uintptr_t)next & 1)) { /*y*/
  1011. if (equals(get_key(next->val), key)) {
  1012. cur->next = next->next;
  1013. --num_elements;
  1014. delete_node(next);
  1015. return 1;
  1016. } else {
  1017. cur = next;
  1018. next = cur->next;
  1019. }
  1020. }
  1021. if (equals(get_key(first->val), key)) {
  1022. buckets[n] = ((uintptr_t)first->next & 1) ? nullptr : first->next; /*y*/
  1023. --num_elements;
  1024. delete_node(first);
  1025. return 1;
  1026. }
  1027. }
  1028. return 0;
  1029. }
  1030. template <class V, class K, class HF, class Ex, class Eq, class A>
  1031. void THashTable<V, K, HF, Ex, Eq, A>::erase(const iterator& it) {
  1032. if (node* const p = it.cur) {
  1033. const size_type n = bkt_num(p->val);
  1034. node* cur = buckets[n];
  1035. if (cur == p) {
  1036. buckets[n] = ((uintptr_t)cur->next & 1) ? nullptr : cur->next; /*y*/
  1037. delete_node(cur);
  1038. --num_elements;
  1039. } else {
  1040. node* next = cur->next;
  1041. while (!((uintptr_t)next & 1)) {
  1042. if (next == p) {
  1043. cur->next = next->next;
  1044. delete_node(next);
  1045. --num_elements;
  1046. break;
  1047. } else {
  1048. cur = next;
  1049. next = cur->next;
  1050. }
  1051. }
  1052. }
  1053. }
  1054. }
  1055. template <class V, class K, class HF, class Ex, class Eq, class A>
  1056. void THashTable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last) {
  1057. size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size(); /*y*/
  1058. size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size(); /*y*/
  1059. if (first.cur == last.cur)
  1060. return;
  1061. else if (f_bucket == l_bucket)
  1062. erase_bucket(f_bucket, first.cur, last.cur);
  1063. else {
  1064. erase_bucket(f_bucket, first.cur, nullptr);
  1065. for (size_type n = f_bucket + 1; n < l_bucket; ++n)
  1066. erase_bucket(n, nullptr);
  1067. if (l_bucket != buckets.size()) /*y*/
  1068. erase_bucket(l_bucket, last.cur);
  1069. }
  1070. }
  1071. template <class V, class K, class HF, class Ex, class Eq, class A>
  1072. inline void
  1073. THashTable<V, K, HF, Ex, Eq, A>::erase(const_iterator first, const_iterator last) {
  1074. erase(iterator(const_cast<node*>(first.cur)), iterator(const_cast<node*>(last.cur)));
  1075. }
  1076. template <class V, class K, class HF, class Ex, class Eq, class A>
  1077. inline void THashTable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it) {
  1078. erase(iterator(const_cast<node*>(it.cur)));
  1079. }
  1080. template <class V, class K, class HF, class Ex, class Eq, class A>
  1081. bool THashTable<V, K, HF, Ex, Eq, A>::reserve(size_type num_elements_hint) {
  1082. const size_type old_n = buckets.size(); /*y*/
  1083. if (num_elements_hint + 1 > old_n) {
  1084. if (old_n != 1 && num_elements_hint <= old_n) // TODO: this if is for backwards compatibility down to order-in-buckets level. Can be safely removed.
  1085. return false;
  1086. const TBucketDivisor n = HashBucketCountExt(num_elements_hint + 1, buckets.BucketDivisorHint() + 1);
  1087. if (n() > old_n) {
  1088. buckets_type tmp(buckets.get_allocator());
  1089. initialize_buckets_dynamic(tmp, n);
  1090. #ifdef __STL_USE_EXCEPTIONS
  1091. try {
  1092. #endif /* __STL_USE_EXCEPTIONS */
  1093. for (size_type bucket = 0; bucket < old_n; ++bucket) {
  1094. node* first = buckets[bucket];
  1095. while (first) {
  1096. size_type new_bucket = bkt_num(first->val, n);
  1097. node* next = first->next;
  1098. buckets[bucket] = ((uintptr_t)next & 1) ? nullptr : next; /*y*/
  1099. next = tmp[new_bucket];
  1100. first->next = next ? next : (node*)((uintptr_t) & (tmp[new_bucket + 1]) | 1); /*y*/
  1101. tmp[new_bucket] = first;
  1102. first = buckets[bucket];
  1103. }
  1104. }
  1105. buckets.swap(tmp);
  1106. deinitialize_buckets(tmp);
  1107. return true;
  1108. #ifdef __STL_USE_EXCEPTIONS
  1109. } catch (...) {
  1110. for (size_type bucket = 0; bucket < tmp.size() - 1; ++bucket) {
  1111. while (tmp[bucket]) {
  1112. node* next = tmp[bucket]->next;
  1113. delete_node(tmp[bucket]);
  1114. tmp[bucket] = ((uintptr_t)next & 1) ? nullptr : next /*y*/;
  1115. }
  1116. }
  1117. throw;
  1118. }
  1119. #endif /* __STL_USE_EXCEPTIONS */
  1120. }
  1121. }
  1122. return false;
  1123. }
  1124. template <class V, class K, class HF, class Ex, class Eq, class A>
  1125. void THashTable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* first, node* last) {
  1126. node* cur = buckets[n];
  1127. if (cur == first)
  1128. erase_bucket(n, last);
  1129. else {
  1130. node* next;
  1131. for (next = cur->next; next != first; cur = next, next = cur->next)
  1132. ;
  1133. while (next != last) { /*y; 3.1*/
  1134. cur->next = next->next;
  1135. delete_node(next);
  1136. next = ((uintptr_t)cur->next & 1) ? nullptr : cur->next; /*y*/
  1137. --num_elements;
  1138. }
  1139. }
  1140. }
  1141. template <class V, class K, class HF, class Ex, class Eq, class A>
  1142. void THashTable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last) {
  1143. node* cur = buckets[n];
  1144. while (cur != last) {
  1145. node* next = cur->next;
  1146. delete_node(cur);
  1147. cur = ((uintptr_t)next & 1) ? nullptr : next; /*y*/
  1148. buckets[n] = cur;
  1149. --num_elements;
  1150. }
  1151. }
  1152. template <class V, class K, class HF, class Ex, class Eq, class A>
  1153. void THashTable<V, K, HF, Ex, Eq, A>::basic_clear() {
  1154. if (!num_elements) {
  1155. return;
  1156. }
  1157. node** first = buckets.begin();
  1158. node** last = buckets.end();
  1159. for (; first < last; ++first) {
  1160. node* cur = *first;
  1161. if (cur) { /*y*/
  1162. while (!((uintptr_t)cur & 1)) { /*y*/
  1163. node* next = cur->next;
  1164. delete_node(cur);
  1165. cur = next;
  1166. }
  1167. *first = nullptr;
  1168. }
  1169. }
  1170. num_elements = 0;
  1171. }
  1172. template <class V, class K, class HF, class Ex, class Eq, class A>
  1173. void THashTable<V, K, HF, Ex, Eq, A>::copy_from_dynamic(const THashTable& ht) {
  1174. Y_ASSERT(buckets.size() == ht.buckets.size() && !ht.empty());
  1175. #ifdef __STL_USE_EXCEPTIONS
  1176. try {
  1177. #endif /* __STL_USE_EXCEPTIONS */
  1178. for (size_type i = 0; i < ht.buckets.size(); ++i) { /*y*/
  1179. if (const node* cur = ht.buckets[i]) {
  1180. node* copy = new_node(cur->val);
  1181. buckets[i] = copy;
  1182. for (node* next = cur->next; !((uintptr_t)next & 1); cur = next, next = cur->next) {
  1183. copy->next = new_node(next->val);
  1184. copy = copy->next;
  1185. }
  1186. copy->next = (node*)((uintptr_t)&buckets[i + 1] | 1); /*y*/
  1187. }
  1188. }
  1189. num_elements = ht.num_elements;
  1190. #ifdef __STL_USE_EXCEPTIONS
  1191. } catch (...) {
  1192. basic_clear();
  1193. throw;
  1194. }
  1195. #endif /* __STL_USE_EXCEPTIONS */
  1196. }
  1197. namespace NPrivate {
  1198. template <class Key>
  1199. inline TString MapKeyToString(const Key&) {
  1200. return TypeName<Key>();
  1201. }
  1202. TString MapKeyToString(TStringBuf key);
  1203. TString MapKeyToString(unsigned short key);
  1204. TString MapKeyToString(short key);
  1205. TString MapKeyToString(unsigned int key);
  1206. TString MapKeyToString(int key);
  1207. TString MapKeyToString(unsigned long key);
  1208. TString MapKeyToString(long key);
  1209. TString MapKeyToString(unsigned long long key);
  1210. TString MapKeyToString(long long key);
  1211. inline TString MapKeyToString(const TString& key) {
  1212. return MapKeyToString(TStringBuf(key));
  1213. }
  1214. inline TString MapKeyToString(const char* key) {
  1215. return MapKeyToString(TStringBuf(key));
  1216. }
  1217. inline TString MapKeyToString(char* key) {
  1218. return MapKeyToString(TStringBuf(key));
  1219. }
  1220. [[noreturn]] void ThrowKeyNotFoundInHashTableException(const TStringBuf keyRepresentation);
  1221. }
  1222. template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
  1223. class THashMap: public TMapOps<THashMap<Key, T, HashFcn, EqualKey, Alloc>> {
  1224. private:
  1225. using ht = THashTable<std::pair<const Key, T>, Key, HashFcn, TSelect1st, EqualKey, Alloc>;
  1226. ht rep;
  1227. public:
  1228. using key_type = typename ht::key_type;
  1229. using value_type = typename ht::value_type;
  1230. using hasher = typename ht::hasher;
  1231. using key_equal = typename ht::key_equal;
  1232. using allocator_type = typename ht::allocator_type;
  1233. using node_allocator_type = typename ht::node_allocator_type;
  1234. using mapped_type = T;
  1235. using size_type = typename ht::size_type;
  1236. using difference_type = typename ht::difference_type;
  1237. using pointer = typename ht::pointer;
  1238. using const_pointer = typename ht::const_pointer;
  1239. using reference = typename ht::reference;
  1240. using const_reference = typename ht::const_reference;
  1241. using iterator = typename ht::iterator;
  1242. using const_iterator = typename ht::const_iterator;
  1243. using insert_ctx = typename ht::insert_ctx;
  1244. hasher hash_function() const {
  1245. return rep.hash_function();
  1246. }
  1247. key_equal key_eq() const {
  1248. return rep.key_eq();
  1249. }
  1250. public:
  1251. THashMap()
  1252. : rep(0, hasher(), key_equal())
  1253. {
  1254. }
  1255. template <class TAllocParam>
  1256. explicit THashMap(TAllocParam* allocParam, size_type n = 0)
  1257. : rep(n, hasher(), key_equal(), allocParam)
  1258. {
  1259. }
  1260. explicit THashMap(size_type n)
  1261. : rep(n, hasher(), key_equal())
  1262. {
  1263. }
  1264. THashMap(size_type n, const hasher& hf)
  1265. : rep(n, hf, key_equal())
  1266. {
  1267. }
  1268. THashMap(size_type n, const hasher& hf, const key_equal& eql)
  1269. : rep(n, hf, eql)
  1270. {
  1271. }
  1272. template <class TAllocParam>
  1273. explicit THashMap(size_type n, TAllocParam* allocParam)
  1274. : rep(n, hasher(), key_equal(), allocParam)
  1275. {
  1276. }
  1277. template <class InputIterator>
  1278. THashMap(InputIterator f, InputIterator l)
  1279. : rep(0, hasher(), key_equal())
  1280. {
  1281. rep.insert_unique(f, l);
  1282. }
  1283. template <class InputIterator>
  1284. THashMap(InputIterator f, InputIterator l, size_type n)
  1285. : rep(n, hasher(), key_equal())
  1286. {
  1287. rep.insert_unique(f, l);
  1288. }
  1289. template <class InputIterator>
  1290. THashMap(InputIterator f, InputIterator l, size_type n,
  1291. const hasher& hf)
  1292. : rep(n, hf, key_equal())
  1293. {
  1294. rep.insert_unique(f, l);
  1295. }
  1296. template <class InputIterator>
  1297. THashMap(InputIterator f, InputIterator l, size_type n,
  1298. const hasher& hf, const key_equal& eql)
  1299. : rep(n, hf, eql)
  1300. {
  1301. rep.insert_unique(f, l);
  1302. }
  1303. THashMap(const std::initializer_list<std::pair<Key, T>>& list)
  1304. : rep(list.size(), hasher(), key_equal())
  1305. {
  1306. for (const auto& v : list) {
  1307. rep.insert_unique_noresize(v);
  1308. }
  1309. }
  1310. // THashMap has implicit copy/move constructors and copy-/move-assignment operators
  1311. // because its implementation is backed by THashTable.
  1312. // See hash_ut.cpp
  1313. public:
  1314. size_type size() const noexcept {
  1315. return rep.size();
  1316. }
  1317. yssize_t ysize() const noexcept {
  1318. return (yssize_t)rep.size();
  1319. }
  1320. size_type max_size() const noexcept {
  1321. return rep.max_size();
  1322. }
  1323. Y_PURE_FUNCTION bool empty() const noexcept {
  1324. return rep.empty();
  1325. }
  1326. explicit operator bool() const noexcept {
  1327. return !empty();
  1328. }
  1329. void swap(THashMap& hs) {
  1330. rep.swap(hs.rep);
  1331. }
  1332. iterator begin() {
  1333. return rep.begin();
  1334. }
  1335. iterator end() {
  1336. return rep.end();
  1337. }
  1338. const_iterator begin() const {
  1339. return rep.begin();
  1340. }
  1341. const_iterator end() const {
  1342. return rep.end();
  1343. }
  1344. const_iterator cbegin() const {
  1345. return rep.begin();
  1346. }
  1347. const_iterator cend() const {
  1348. return rep.end();
  1349. }
  1350. public:
  1351. template <class InputIterator>
  1352. void insert(InputIterator f, InputIterator l) {
  1353. rep.insert_unique(f, l);
  1354. }
  1355. std::pair<iterator, bool> insert(const value_type& obj) {
  1356. return rep.insert_unique(obj);
  1357. }
  1358. template <typename... Args>
  1359. std::pair<iterator, bool> emplace(Args&&... args) {
  1360. return rep.emplace_unique(std::forward<Args>(args)...);
  1361. }
  1362. std::pair<iterator, bool> insert_noresize(const value_type& obj) {
  1363. return rep.insert_unique_noresize(obj);
  1364. }
  1365. template <typename... Args>
  1366. std::pair<iterator, bool> emplace_noresize(Args&&... args) {
  1367. return rep.emplace_unique_noresize(std::forward<Args>(args)...);
  1368. }
  1369. template <class TheObj>
  1370. iterator insert_direct(const TheObj& obj, const insert_ctx& ins) {
  1371. return rep.insert_direct(obj, ins);
  1372. }
  1373. template <typename... Args>
  1374. iterator emplace_direct(const insert_ctx& ins, Args&&... args) {
  1375. return rep.emplace_direct(ins, std::forward<Args>(args)...);
  1376. }
  1377. template <typename TKey, typename... Args>
  1378. std::pair<iterator, bool> try_emplace(TKey&& key, Args&&... args) {
  1379. insert_ctx ctx = nullptr;
  1380. iterator it = find(key, ctx);
  1381. if (it == end()) {
  1382. it = rep.emplace_direct(ctx, std::piecewise_construct,
  1383. std::forward_as_tuple(std::forward<TKey>(key)),
  1384. std::forward_as_tuple(std::forward<Args>(args)...));
  1385. return {it, true};
  1386. }
  1387. return {it, false};
  1388. }
  1389. template <class TheKey>
  1390. iterator find(const TheKey& key) {
  1391. return rep.find(key);
  1392. }
  1393. template <class TheKey>
  1394. const_iterator find(const TheKey& key) const {
  1395. return rep.find(key);
  1396. }
  1397. template <class TheKey>
  1398. iterator find(const TheKey& key, insert_ctx& ins) {
  1399. return rep.find_i(key, ins);
  1400. }
  1401. template <class TheKey>
  1402. bool contains(const TheKey& key) const {
  1403. return rep.find(key) != rep.end();
  1404. }
  1405. bool contains(const key_type& key) const {
  1406. return rep.find(key) != rep.end();
  1407. }
  1408. template <class TheKey>
  1409. bool contains(const TheKey& key, insert_ctx& ins) {
  1410. return rep.find_i(key, ins) != rep.end();
  1411. }
  1412. template <class TKey>
  1413. T& operator[](const TKey& key) {
  1414. insert_ctx ctx = nullptr;
  1415. iterator it = find(key, ctx);
  1416. if (it != end()) {
  1417. return it->second;
  1418. }
  1419. return rep.emplace_direct(ctx, std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple())->second;
  1420. }
  1421. template <class TheKey>
  1422. const T& at(const TheKey& key) const {
  1423. using namespace ::NPrivate;
  1424. const_iterator it = find(key);
  1425. if (Y_UNLIKELY(it == end())) {
  1426. ::NPrivate::ThrowKeyNotFoundInHashTableException(MapKeyToString(key));
  1427. }
  1428. return it->second;
  1429. }
  1430. template <class TheKey>
  1431. T& at(const TheKey& key) {
  1432. using namespace ::NPrivate;
  1433. iterator it = find(key);
  1434. if (Y_UNLIKELY(it == end())) {
  1435. ::NPrivate::ThrowKeyNotFoundInHashTableException(MapKeyToString(key));
  1436. }
  1437. return it->second;
  1438. }
  1439. template <class TKey>
  1440. size_type count(const TKey& key) const {
  1441. return rep.count(key);
  1442. }
  1443. template <class TKey>
  1444. std::pair<iterator, iterator> equal_range(const TKey& key) {
  1445. return rep.equal_range(key);
  1446. }
  1447. template <class TKey>
  1448. std::pair<const_iterator, const_iterator> equal_range(const TKey& key) const {
  1449. return rep.equal_range(key);
  1450. }
  1451. template <class TKey>
  1452. size_type erase(const TKey& key) {
  1453. return rep.erase_one(key);
  1454. }
  1455. void erase(iterator it) {
  1456. rep.erase(it);
  1457. }
  1458. void erase(iterator f, iterator l) {
  1459. rep.erase(f, l);
  1460. }
  1461. void clear() {
  1462. rep.clear();
  1463. }
  1464. void clear(size_t downsize_hint) {
  1465. rep.clear(downsize_hint);
  1466. }
  1467. void basic_clear() {
  1468. rep.basic_clear();
  1469. }
  1470. void release_nodes() {
  1471. rep.release_nodes();
  1472. }
  1473. // if (stHash != NULL) bucket_count() must be equal to stHash->bucket_count()
  1474. template <class KeySaver>
  1475. int save_for_st(IOutputStream* stream, KeySaver& ks, sthash<int, int, THash<int>, TEqualTo<int>, typename KeySaver::TSizeType>* stHash = nullptr) const {
  1476. return rep.template save_for_st<KeySaver>(stream, ks, stHash);
  1477. }
  1478. public:
  1479. void reserve(size_type hint) {
  1480. rep.reserve(hint);
  1481. }
  1482. size_type bucket_count() const {
  1483. return rep.bucket_count();
  1484. }
  1485. size_type bucket_size(size_type n) const {
  1486. return rep.bucket_size(n);
  1487. }
  1488. node_allocator_type& GetNodeAllocator() {
  1489. return rep.GetNodeAllocator();
  1490. }
  1491. const node_allocator_type& GetNodeAllocator() const {
  1492. return rep.GetNodeAllocator();
  1493. }
  1494. };
  1495. template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
  1496. inline bool operator==(const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm1, const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm2) {
  1497. if (hm1.size() != hm2.size()) {
  1498. return false;
  1499. }
  1500. for (const auto& it1 : hm1) {
  1501. auto it2 = hm2.find(it1.first);
  1502. if ((it2 == hm2.end()) || !(it1 == *it2)) {
  1503. return false;
  1504. }
  1505. }
  1506. return true;
  1507. }
  1508. template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
  1509. inline bool operator!=(const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm1, const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm2) {
  1510. return !(hm1 == hm2);
  1511. }
  1512. template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
  1513. class THashMultiMap {
  1514. private:
  1515. using ht = THashTable<std::pair<const Key, T>, Key, HashFcn, TSelect1st, EqualKey, Alloc>;
  1516. ht rep;
  1517. public:
  1518. using key_type = typename ht::key_type;
  1519. using value_type = typename ht::value_type;
  1520. using hasher = typename ht::hasher;
  1521. using key_equal = typename ht::key_equal;
  1522. using mapped_type = T;
  1523. using allocator_type = typename ht::allocator_type;
  1524. using size_type = typename ht::size_type;
  1525. using difference_type = typename ht::difference_type;
  1526. using pointer = typename ht::pointer;
  1527. using const_pointer = typename ht::const_pointer;
  1528. using reference = typename ht::reference;
  1529. using const_reference = typename ht::const_reference;
  1530. using iterator = typename ht::iterator;
  1531. using const_iterator = typename ht::const_iterator;
  1532. using insert_ctx = typename ht::insert_ctx;
  1533. hasher hash_function() const {
  1534. return rep.hash_function();
  1535. }
  1536. key_equal key_eq() const {
  1537. return rep.key_eq();
  1538. }
  1539. public:
  1540. THashMultiMap()
  1541. : rep(0, hasher(), key_equal())
  1542. {
  1543. }
  1544. template <typename TAllocParam>
  1545. explicit THashMultiMap(TAllocParam* allocParam)
  1546. : rep(0, hasher(), key_equal(), allocParam)
  1547. {
  1548. }
  1549. explicit THashMultiMap(size_type n)
  1550. : rep(n, hasher(), key_equal())
  1551. {
  1552. }
  1553. THashMultiMap(size_type n, const hasher& hf)
  1554. : rep(n, hf, key_equal())
  1555. {
  1556. }
  1557. THashMultiMap(size_type n, const hasher& hf, const key_equal& eql)
  1558. : rep(n, hf, eql)
  1559. {
  1560. }
  1561. template <class InputIterator>
  1562. THashMultiMap(InputIterator f, InputIterator l)
  1563. : rep(0, hasher(), key_equal())
  1564. {
  1565. rep.insert_equal(f, l);
  1566. }
  1567. template <class InputIterator>
  1568. THashMultiMap(InputIterator f, InputIterator l, size_type n)
  1569. : rep(n, hasher(), key_equal())
  1570. {
  1571. rep.insert_equal(f, l);
  1572. }
  1573. template <class InputIterator>
  1574. THashMultiMap(InputIterator f, InputIterator l, size_type n, const hasher& hf)
  1575. : rep(n, hf, key_equal())
  1576. {
  1577. rep.insert_equal(f, l);
  1578. }
  1579. template <class InputIterator>
  1580. THashMultiMap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const key_equal& eql)
  1581. : rep(n, hf, eql)
  1582. {
  1583. rep.insert_equal(f, l);
  1584. }
  1585. THashMultiMap(std::initializer_list<std::pair<Key, T>> list)
  1586. : rep(list.size(), hasher(), key_equal())
  1587. {
  1588. for (const auto& v : list) {
  1589. rep.emplace_equal_noresize(v);
  1590. }
  1591. }
  1592. // THashMultiMap has implicit copy/move constructors and copy-/move-assignment operators
  1593. // because its implementation is backed by THashTable.
  1594. // See hash_ut.cpp
  1595. public:
  1596. size_type size() const {
  1597. return rep.size();
  1598. }
  1599. yssize_t ysize() const {
  1600. return (yssize_t)rep.size();
  1601. }
  1602. size_type max_size() const {
  1603. return rep.max_size();
  1604. }
  1605. Y_PURE_FUNCTION bool empty() const {
  1606. return rep.empty();
  1607. }
  1608. explicit operator bool() const noexcept {
  1609. return !empty();
  1610. }
  1611. void swap(THashMultiMap& hs) {
  1612. rep.swap(hs.rep);
  1613. }
  1614. iterator begin() {
  1615. return rep.begin();
  1616. }
  1617. iterator end() {
  1618. return rep.end();
  1619. }
  1620. const_iterator begin() const {
  1621. return rep.begin();
  1622. }
  1623. const_iterator end() const {
  1624. return rep.end();
  1625. }
  1626. const_iterator cbegin() const {
  1627. return rep.begin();
  1628. }
  1629. const_iterator cend() const {
  1630. return rep.end();
  1631. }
  1632. public:
  1633. template <class InputIterator>
  1634. void insert(InputIterator f, InputIterator l) {
  1635. rep.insert_equal(f, l);
  1636. }
  1637. iterator insert(const value_type& obj) {
  1638. return rep.insert_equal(obj);
  1639. }
  1640. template <typename... Args>
  1641. iterator emplace(Args&&... args) {
  1642. return rep.emplace_equal(std::forward<Args>(args)...);
  1643. }
  1644. iterator insert_noresize(const value_type& obj) {
  1645. return rep.emplace_equal_noresize(obj);
  1646. }
  1647. template <typename... Args>
  1648. iterator emplace_noresize(Args&&... args) {
  1649. return rep.emplace_equal_noresize(std::forward<Args>(args)...);
  1650. }
  1651. template <class TheObj>
  1652. iterator insert_direct(const TheObj& obj, const insert_ctx& ins) {
  1653. return rep.insert_direct(obj, ins);
  1654. }
  1655. template <typename... Args>
  1656. iterator emplace_direct(const insert_ctx& ins, Args&&... args) {
  1657. return rep.emplace_direct(ins, std::forward<Args>(args)...);
  1658. }
  1659. template <class TKey>
  1660. const_iterator find(const TKey& key) const {
  1661. return rep.find(key);
  1662. }
  1663. template <class TKey>
  1664. iterator find(const TKey& key) {
  1665. return rep.find(key);
  1666. }
  1667. template <class TheKey>
  1668. iterator find(const TheKey& key, insert_ctx& ins) {
  1669. return rep.find_i(key, ins);
  1670. }
  1671. template <class TheKey>
  1672. bool contains(const TheKey& key) const {
  1673. return rep.find(key) != rep.end();
  1674. }
  1675. template <class TKey>
  1676. size_type count(const TKey& key) const {
  1677. return rep.count(key);
  1678. }
  1679. template <class TKey>
  1680. std::pair<iterator, iterator> equal_range(const TKey& key) {
  1681. return rep.equal_range(key);
  1682. }
  1683. template <class TKey>
  1684. std::pair<const_iterator, const_iterator> equal_range(const TKey& key) const {
  1685. return rep.equal_range(key);
  1686. }
  1687. size_type erase(const key_type& key) {
  1688. return rep.erase(key);
  1689. }
  1690. void erase(iterator it) {
  1691. rep.erase(it);
  1692. }
  1693. void erase(iterator f, iterator l) {
  1694. rep.erase(f, l);
  1695. }
  1696. void clear() {
  1697. rep.clear();
  1698. }
  1699. void clear(size_t downsize_hint) {
  1700. rep.clear(downsize_hint);
  1701. }
  1702. void basic_clear() {
  1703. rep.basic_clear();
  1704. }
  1705. void release_nodes() {
  1706. rep.release_nodes();
  1707. }
  1708. // if (stHash != NULL) bucket_count() must be equal to stHash->bucket_count()
  1709. template <class KeySaver>
  1710. int save_for_st(IOutputStream* stream, KeySaver& ks, sthash<int, int, THash<int>, TEqualTo<int>, typename KeySaver::TSizeType>* stHash = nullptr) const {
  1711. return rep.template save_for_st<KeySaver>(stream, ks, stHash);
  1712. }
  1713. public:
  1714. void reserve(size_type hint) {
  1715. rep.reserve(hint);
  1716. }
  1717. size_type bucket_count() const {
  1718. return rep.bucket_count();
  1719. }
  1720. size_type bucket_size(size_type n) const {
  1721. return rep.bucket_size(n);
  1722. }
  1723. };
  1724. template <class Key, class T, class HF, class EqKey, class Alloc>
  1725. inline bool operator==(const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm1, const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm2) {
  1726. // NOTE: copy-pasted from
  1727. // contrib/libs/cxxsupp/libcxx/include/unordered_map
  1728. // and adapted to THashMultiMap
  1729. if (hm1.size() != hm2.size()) {
  1730. return false;
  1731. }
  1732. using const_iterator = typename THashMultiMap<Key, T, HF, EqKey, Alloc>::const_iterator;
  1733. using TEqualRange = std::pair<const_iterator, const_iterator>;
  1734. for (const_iterator it = hm1.begin(), end = hm1.end(); it != end;) {
  1735. TEqualRange eq1 = hm1.equal_range(it->first);
  1736. TEqualRange eq2 = hm2.equal_range(it->first);
  1737. if (std::distance(eq1.first, eq1.second) != std::distance(eq2.first, eq2.second) ||
  1738. !std::is_permutation(eq1.first, eq1.second, eq2.first))
  1739. {
  1740. return false;
  1741. }
  1742. it = eq1.second;
  1743. }
  1744. return true;
  1745. }
  1746. template <class Key, class T, class HF, class EqKey, class Alloc>
  1747. inline bool operator!=(const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm1, const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm2) {
  1748. return !(hm1 == hm2);
  1749. }
  1750. // Cannot name it just 'Hash' because it clashes with too many class members in the code.
  1751. template <class T>
  1752. size_t ComputeHash(const T& value) {
  1753. return THash<T>{}(value);
  1754. }