blob: 8f1d328f0e0f45b468d300d99bda9ae727186fdc [file] [log] [blame]
Louis Dionne9bd93882021-11-17 16:25:01 -05001//===----------------------------------------------------------------------===//
Howard Hinnant27e0e772011-09-14 18:33:51 +00002//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnant27e0e772011-09-14 18:33:51 +00006//
7//===----------------------------------------------------------------------===//
8
Louis Dionne9bdbeb32022-02-14 13:41:09 -05009#include <__assert>
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -050010#include <__config>
11#include <__debug>
12#include <__hash_table>
13#include <algorithm>
14#include <cstdio>
15#include <functional>
16#include <string>
17
Petr Hosek99575aa2019-05-30 01:34:41 +000018#ifndef _LIBCPP_HAS_NO_THREADS
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -050019# include <mutex>
20# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
21# pragma comment(lib, "pthread")
22# endif
Petr Hosek99575aa2019-05-30 01:34:41 +000023#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +000024
25_LIBCPP_BEGIN_NAMESPACE_STD
26
Howard Hinnant8331b762013-03-06 23:30:19 +000027_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000028__libcpp_db*
29__get_db()
30{
Louis Dionnea39f1ef2019-04-17 18:20:19 +000031 static _LIBCPP_NO_DESTROY __libcpp_db db;
Howard Hinnant27e0e772011-09-14 18:33:51 +000032 return &db;
Howard Hinnant434ebf72012-12-27 18:46:00 +000033}
Howard Hinnant27e0e772011-09-14 18:33:51 +000034
Howard Hinnant8331b762013-03-06 23:30:19 +000035_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000036const __libcpp_db*
37__get_const_db()
38{
39 return __get_db();
40}
41
42namespace
43{
44
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000045#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +000046typedef mutex mutex_type;
Howard Hinnant27e0e772011-09-14 18:33:51 +000047typedef lock_guard<mutex_type> WLock;
48typedef lock_guard<mutex_type> RLock;
49
50mutex_type&
51mut()
52{
Louis Dionnea39f1ef2019-04-17 18:20:19 +000053 static _LIBCPP_NO_DESTROY mutex_type m;
Howard Hinnant27e0e772011-09-14 18:33:51 +000054 return m;
55}
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000056#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +000057
58} // unnamed namespace
59
60__i_node::~__i_node()
61{
62 if (__next_)
63 {
64 __next_->~__i_node();
65 free(__next_);
66 }
67}
68
69__c_node::~__c_node()
70{
71 free(beg_);
72 if (__next_)
73 {
74 __next_->~__c_node();
75 free(__next_);
76 }
77}
78
79__libcpp_db::__libcpp_db()
80 : __cbeg_(nullptr),
81 __cend_(nullptr),
82 __csz_(0),
83 __ibeg_(nullptr),
84 __iend_(nullptr),
85 __isz_(0)
86{
87}
88
89__libcpp_db::~__libcpp_db()
90{
91 if (__cbeg_)
92 {
93 for (__c_node** p = __cbeg_; p != __cend_; ++p)
94 {
95 if (*p != nullptr)
96 {
97 (*p)->~__c_node();
98 free(*p);
99 }
100 }
101 free(__cbeg_);
102 }
103 if (__ibeg_)
104 {
105 for (__i_node** p = __ibeg_; p != __iend_; ++p)
106 {
107 if (*p != nullptr)
108 {
109 (*p)->~__i_node();
110 free(*p);
111 }
112 }
113 free(__ibeg_);
114 }
115}
116
117void*
118__libcpp_db::__find_c_from_i(void* __i) const
119{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000120#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000121 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000122#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000123 __i_node* i = __find_iterator(__i);
Howard Hinnant17e485c2013-04-05 17:58:52 +0000124 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
Howard Hinnantc90aa632011-09-16 19:52:23 +0000125 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000126}
127
128void
129__libcpp_db::__insert_ic(void* __i, const void* __c)
130{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000131#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000132 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000133#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000134 if (__cbeg_ == __cend_)
135 return;
Howard Hinnant28b24882011-12-01 20:21:04 +0000136 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000137 __c_node* c = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000138 if (c == nullptr)
139 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000140 while (c->__c_ != __c)
141 {
142 c = c->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000143 if (c == nullptr)
144 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000145 }
Howard Hinnant8ea98242013-08-23 17:37:05 +0000146 __i_node* i = __insert_iterator(__i);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000147 c->__add(i);
148 i->__c_ = c;
149}
150
Eric Fiselieraed4eab2019-03-05 02:10:31 +0000151void
152__libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000153{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000154#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000155 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000156#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000157 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000158 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000159 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
Louis Dionne71c42dd2019-04-17 16:11:41 +0000160 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000161 if (cbeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000162 __throw_bad_alloc();
163
Howard Hinnant27e0e772011-09-14 18:33:51 +0000164 for (__c_node** p = __cbeg_; p != __cend_; ++p)
165 {
166 __c_node* q = *p;
167 while (q != nullptr)
168 {
169 size_t h = hash<void*>()(q->__c_) % nc;
170 __c_node* r = q->__next_;
171 q->__next_ = cbeg[h];
172 cbeg[h] = q;
173 q = r;
174 }
175 }
176 free(__cbeg_);
177 __cbeg_ = cbeg;
178 __cend_ = __cbeg_ + nc;
179 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000180 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000181 __c_node* p = __cbeg_[hc];
Eric Fiselieraed4eab2019-03-05 02:10:31 +0000182 void *buf = malloc(sizeof(__c_node));
183 if (buf == nullptr)
184 __throw_bad_alloc();
185 __cbeg_[hc] = __fn(buf, __c, p);
Marshall Clow8fea1612016-08-25 15:09:01 +0000186
Howard Hinnant27e0e772011-09-14 18:33:51 +0000187 ++__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000188}
189
190void
191__libcpp_db::__erase_i(void* __i)
192{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000193#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000194 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000195#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000196 if (__ibeg_ != __iend_)
197 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000198 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000199 __i_node* p = __ibeg_[hi];
200 if (p != nullptr)
201 {
202 __i_node* q = nullptr;
203 while (p->__i_ != __i)
204 {
205 q = p;
206 p = p->__next_;
207 if (p == nullptr)
208 return;
209 }
210 if (q == nullptr)
211 __ibeg_[hi] = p->__next_;
212 else
213 q->__next_ = p->__next_;
214 __c_node* c = p->__c_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000215 --__isz_;
216 if (c != nullptr)
217 c->__remove(p);
Eric Fiselier799b25d2015-03-19 03:20:02 +0000218 free(p);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000219 }
220 }
221}
222
223void
224__libcpp_db::__invalidate_all(void* __c)
225{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000226#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000227 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000228#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000229 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000230 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000231 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
232 __c_node* p = __cbeg_[hc];
233 if (p == nullptr)
234 return;
235 while (p->__c_ != __c)
236 {
237 p = p->__next_;
238 if (p == nullptr)
239 return;
240 }
241 while (p->end_ != p->beg_)
242 {
243 --p->end_;
244 (*p->end_)->__c_ = nullptr;
245 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000246 }
247}
248
249__c_node*
250__libcpp_db::__find_c_and_lock(void* __c) const
251{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000252#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000253 mut().lock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000254#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000255 if (__cend_ == __cbeg_)
256 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000257#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000258 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000259#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000260 return nullptr;
261 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000262 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000263 __c_node* p = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000264 if (p == nullptr)
265 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000266#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000267 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000268#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000269 return nullptr;
270 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000271 while (p->__c_ != __c)
272 {
273 p = p->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000274 if (p == nullptr)
275 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000276#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000277 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000278#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000279 return nullptr;
280 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000281 }
282 return p;
283}
284
Howard Hinnantb399c602011-09-27 23:55:03 +0000285__c_node*
286__libcpp_db::__find_c(void* __c) const
287{
Howard Hinnant28b24882011-12-01 20:21:04 +0000288 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000289 __c_node* p = __cbeg_[hc];
290 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
291 while (p->__c_ != __c)
292 {
293 p = p->__next_;
294 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
295 }
296 return p;
297}
298
Howard Hinnant27e0e772011-09-14 18:33:51 +0000299void
300__libcpp_db::unlock() const
301{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000302#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000303 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000304#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000305}
306
307void
308__libcpp_db::__erase_c(void* __c)
309{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000310#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000311 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000312#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000313 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000314 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000315 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
316 __c_node* p = __cbeg_[hc];
317 if (p == nullptr)
318 return;
319 __c_node* q = nullptr;
320 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
321 while (p->__c_ != __c)
322 {
323 q = p;
324 p = p->__next_;
325 if (p == nullptr)
326 return;
327 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
328 }
329 if (q == nullptr)
330 __cbeg_[hc] = p->__next_;
331 else
332 q->__next_ = p->__next_;
333 while (p->end_ != p->beg_)
334 {
335 --p->end_;
336 (*p->end_)->__c_ = nullptr;
337 }
338 free(p->beg_);
339 free(p);
340 --__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000341 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000342}
343
344void
345__libcpp_db::__iterator_copy(void* __i, const void* __i0)
346{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000347#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000348 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000349#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000350 __i_node* i = __find_iterator(__i);
351 __i_node* i0 = __find_iterator(__i0);
352 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
Howard Hinnant17e485c2013-04-05 17:58:52 +0000353 if (i == nullptr && i0 != nullptr)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000354 i = __insert_iterator(__i);
355 __c_node* c = i != nullptr ? i->__c_ : nullptr;
356 if (c != c0)
357 {
358 if (c != nullptr)
359 c->__remove(i);
360 if (i != nullptr)
361 {
362 i->__c_ = nullptr;
363 if (c0 != nullptr)
364 {
365 i->__c_ = c0;
366 i->__c_->__add(i);
367 }
368 }
369 }
370}
371
372bool
373__libcpp_db::__dereferenceable(const void* __i) const
374{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000375#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000376 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000377#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000378 __i_node* i = __find_iterator(__i);
379 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
380}
381
382bool
383__libcpp_db::__decrementable(const void* __i) const
384{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000385#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000386 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000387#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000388 __i_node* i = __find_iterator(__i);
389 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
390}
391
392bool
393__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
394{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000395#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000396 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000397#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000398 __i_node* i = __find_iterator(__i);
399 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
400}
401
402bool
403__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
404{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000405#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000406 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000407#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000408 __i_node* i = __find_iterator(__i);
409 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
410}
411
412bool
Howard Hinnante6ff0b62013-08-02 00:26:35 +0000413__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
Howard Hinnant27e0e772011-09-14 18:33:51 +0000414{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000415#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000416 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000417#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000418 __i_node* i = __find_iterator(__i);
419 __i_node* j = __find_iterator(__j);
420 __c_node* ci = i != nullptr ? i->__c_ : nullptr;
421 __c_node* cj = j != nullptr ? j->__c_ : nullptr;
Arthur O'Dwyer11eb4b32021-04-20 11:25:37 -0400422 return ci == cj;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000423}
424
425void
426__libcpp_db::swap(void* c1, void* c2)
427{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000428#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000429 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000430#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000431 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000432 __c_node* p1 = __cbeg_[hc];
433 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
434 while (p1->__c_ != c1)
435 {
436 p1 = p1->__next_;
437 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
438 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000439 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000440 __c_node* p2 = __cbeg_[hc];
441 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
442 while (p2->__c_ != c2)
443 {
444 p2 = p2->__next_;
445 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
446 }
447 std::swap(p1->beg_, p2->beg_);
448 std::swap(p1->end_, p2->end_);
449 std::swap(p1->cap_, p2->cap_);
450 for (__i_node** p = p1->beg_; p != p1->end_; ++p)
451 (*p)->__c_ = p1;
452 for (__i_node** p = p2->beg_; p != p2->end_; ++p)
453 (*p)->__c_ = p2;
454}
455
Howard Hinnantc90aa632011-09-16 19:52:23 +0000456void
457__libcpp_db::__insert_i(void* __i)
458{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000459#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantc90aa632011-09-16 19:52:23 +0000460 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000461#endif
Howard Hinnantc90aa632011-09-16 19:52:23 +0000462 __insert_iterator(__i);
463}
464
Howard Hinnantb399c602011-09-27 23:55:03 +0000465void
466__c_node::__add(__i_node* i)
467{
468 if (end_ == cap_)
469 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000470 size_t nc = 2*static_cast<size_t>(cap_ - beg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000471 if (nc == 0)
472 nc = 1;
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000473 __i_node** beg =
474 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
Howard Hinnantb399c602011-09-27 23:55:03 +0000475 if (beg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000476 __throw_bad_alloc();
477
Howard Hinnantb399c602011-09-27 23:55:03 +0000478 if (nc > 1)
479 memcpy(beg, beg_, nc/2*sizeof(__i_node*));
480 free(beg_);
481 beg_ = beg;
482 end_ = beg_ + nc/2;
483 cap_ = beg_ + nc;
484 }
485 *end_++ = i;
486}
487
Howard Hinnant27e0e772011-09-14 18:33:51 +0000488// private api
489
490_LIBCPP_HIDDEN
491__i_node*
492__libcpp_db::__insert_iterator(void* __i)
493{
Howard Hinnant28b24882011-12-01 20:21:04 +0000494 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000495 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000496 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
Louis Dionne71c42dd2019-04-17 16:11:41 +0000497 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000498 if (ibeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000499 __throw_bad_alloc();
500
Howard Hinnant27e0e772011-09-14 18:33:51 +0000501 for (__i_node** p = __ibeg_; p != __iend_; ++p)
502 {
503 __i_node* q = *p;
504 while (q != nullptr)
505 {
506 size_t h = hash<void*>()(q->__i_) % nc;
507 __i_node* r = q->__next_;
508 q->__next_ = ibeg[h];
509 ibeg[h] = q;
510 q = r;
511 }
512 }
513 free(__ibeg_);
514 __ibeg_ = ibeg;
515 __iend_ = __ibeg_ + nc;
516 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000517 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000518 __i_node* p = __ibeg_[hi];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000519 __i_node* r = __ibeg_[hi] =
520 static_cast<__i_node*>(malloc(sizeof(__i_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000521 if (r == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000522 __throw_bad_alloc();
523
Howard Hinnant27e0e772011-09-14 18:33:51 +0000524 ::new(r) __i_node(__i, p, nullptr);
525 ++__isz_;
526 return r;
527}
528
529_LIBCPP_HIDDEN
530__i_node*
531__libcpp_db::__find_iterator(const void* __i) const
532{
533 __i_node* r = nullptr;
534 if (__ibeg_ != __iend_)
535 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000536 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000537 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
538 {
539 if (nd->__i_ == __i)
540 {
541 r = nd;
542 break;
543 }
544 }
545 }
546 return r;
547}
548
549_LIBCPP_HIDDEN
550void
Howard Hinnant27e0e772011-09-14 18:33:51 +0000551__c_node::__remove(__i_node* p)
552{
553 __i_node** r = find(beg_, end_, p);
554 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
555 if (--end_ != r)
Howard Hinnant28b24882011-12-01 20:21:04 +0000556 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000557}
558
559_LIBCPP_END_NAMESPACE_STD