blob: 15d8fdb8816ba2a28b26679238bde056e7215f80 [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
Howard Hinnanta47c6d52011-09-16 17:29:17 +00009#include "__config"
Howard Hinnant27e0e772011-09-14 18:33:51 +000010#include "__debug"
11#include "functional"
12#include "algorithm"
Eric Fiselierfb825432016-12-28 04:58:52 +000013#include "string"
14#include "cstdio"
Howard Hinnant27e0e772011-09-14 18:33:51 +000015#include "__hash_table"
Petr Hosek99575aa2019-05-30 01:34:41 +000016#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +000017#include "mutex"
Michał Górny8d676fb2019-12-02 11:49:20 +010018#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
Petr Hosek99575aa2019-05-30 01:34:41 +000019#pragma comment(lib, "pthread")
20#endif
21#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +000022
23_LIBCPP_BEGIN_NAMESPACE_STD
24
Eric Fiselier873b8d32019-03-18 21:50:12 +000025std::string __libcpp_debug_info::what() const {
26 string msg = __file_;
27 msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '";
28 msg += __pred_;
Eric Fiselierfb825432016-12-28 04:58:52 +000029 msg += "' failed. ";
Eric Fiselier873b8d32019-03-18 21:50:12 +000030 msg += __msg_;
Eric Fiselierfb825432016-12-28 04:58:52 +000031 return msg;
32}
Eric Fiselier873b8d32019-03-18 21:50:12 +000033_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
34 std::fprintf(stderr, "%s\n", info.what().c_str());
35 std::abort();
36}
Eric Fiselierfb825432016-12-28 04:58:52 +000037
Arthur O'Dwyer209ff392022-02-08 13:08:59 -050038constinit __libcpp_debug_function_type __libcpp_debug_function = __libcpp_abort_debug_function;
Eric Fiselierfb825432016-12-28 04:58:52 +000039
40bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
41 __libcpp_debug_function = __func;
42 return true;
43}
44
Howard Hinnant8331b762013-03-06 23:30:19 +000045_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000046__libcpp_db*
47__get_db()
48{
Louis Dionnea39f1ef2019-04-17 18:20:19 +000049 static _LIBCPP_NO_DESTROY __libcpp_db db;
Howard Hinnant27e0e772011-09-14 18:33:51 +000050 return &db;
Howard Hinnant434ebf72012-12-27 18:46:00 +000051}
Howard Hinnant27e0e772011-09-14 18:33:51 +000052
Howard Hinnant8331b762013-03-06 23:30:19 +000053_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000054const __libcpp_db*
55__get_const_db()
56{
57 return __get_db();
58}
59
60namespace
61{
62
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000063#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +000064typedef mutex mutex_type;
Howard Hinnant27e0e772011-09-14 18:33:51 +000065typedef lock_guard<mutex_type> WLock;
66typedef lock_guard<mutex_type> RLock;
67
68mutex_type&
69mut()
70{
Louis Dionnea39f1ef2019-04-17 18:20:19 +000071 static _LIBCPP_NO_DESTROY mutex_type m;
Howard Hinnant27e0e772011-09-14 18:33:51 +000072 return m;
73}
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000074#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +000075
76} // unnamed namespace
77
78__i_node::~__i_node()
79{
80 if (__next_)
81 {
82 __next_->~__i_node();
83 free(__next_);
84 }
85}
86
87__c_node::~__c_node()
88{
89 free(beg_);
90 if (__next_)
91 {
92 __next_->~__c_node();
93 free(__next_);
94 }
95}
96
97__libcpp_db::__libcpp_db()
98 : __cbeg_(nullptr),
99 __cend_(nullptr),
100 __csz_(0),
101 __ibeg_(nullptr),
102 __iend_(nullptr),
103 __isz_(0)
104{
105}
106
107__libcpp_db::~__libcpp_db()
108{
109 if (__cbeg_)
110 {
111 for (__c_node** p = __cbeg_; p != __cend_; ++p)
112 {
113 if (*p != nullptr)
114 {
115 (*p)->~__c_node();
116 free(*p);
117 }
118 }
119 free(__cbeg_);
120 }
121 if (__ibeg_)
122 {
123 for (__i_node** p = __ibeg_; p != __iend_; ++p)
124 {
125 if (*p != nullptr)
126 {
127 (*p)->~__i_node();
128 free(*p);
129 }
130 }
131 free(__ibeg_);
132 }
133}
134
135void*
136__libcpp_db::__find_c_from_i(void* __i) const
137{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000138#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000139 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000140#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000141 __i_node* i = __find_iterator(__i);
Howard Hinnant17e485c2013-04-05 17:58:52 +0000142 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
Howard Hinnantc90aa632011-09-16 19:52:23 +0000143 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000144}
145
146void
147__libcpp_db::__insert_ic(void* __i, const void* __c)
148{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000149#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000150 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000151#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000152 if (__cbeg_ == __cend_)
153 return;
Howard Hinnant28b24882011-12-01 20:21:04 +0000154 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000155 __c_node* c = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000156 if (c == nullptr)
157 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000158 while (c->__c_ != __c)
159 {
160 c = c->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000161 if (c == nullptr)
162 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000163 }
Howard Hinnant8ea98242013-08-23 17:37:05 +0000164 __i_node* i = __insert_iterator(__i);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000165 c->__add(i);
166 i->__c_ = c;
167}
168
Eric Fiselieraed4eab2019-03-05 02:10:31 +0000169void
170__libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000171{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000172#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000173 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000174#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000175 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000176 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000177 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
Louis Dionne71c42dd2019-04-17 16:11:41 +0000178 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000179 if (cbeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000180 __throw_bad_alloc();
181
Howard Hinnant27e0e772011-09-14 18:33:51 +0000182 for (__c_node** p = __cbeg_; p != __cend_; ++p)
183 {
184 __c_node* q = *p;
185 while (q != nullptr)
186 {
187 size_t h = hash<void*>()(q->__c_) % nc;
188 __c_node* r = q->__next_;
189 q->__next_ = cbeg[h];
190 cbeg[h] = q;
191 q = r;
192 }
193 }
194 free(__cbeg_);
195 __cbeg_ = cbeg;
196 __cend_ = __cbeg_ + nc;
197 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000198 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000199 __c_node* p = __cbeg_[hc];
Eric Fiselieraed4eab2019-03-05 02:10:31 +0000200 void *buf = malloc(sizeof(__c_node));
201 if (buf == nullptr)
202 __throw_bad_alloc();
203 __cbeg_[hc] = __fn(buf, __c, p);
Marshall Clow8fea1612016-08-25 15:09:01 +0000204
Howard Hinnant27e0e772011-09-14 18:33:51 +0000205 ++__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000206}
207
208void
209__libcpp_db::__erase_i(void* __i)
210{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000211#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000212 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000213#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000214 if (__ibeg_ != __iend_)
215 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000216 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000217 __i_node* p = __ibeg_[hi];
218 if (p != nullptr)
219 {
220 __i_node* q = nullptr;
221 while (p->__i_ != __i)
222 {
223 q = p;
224 p = p->__next_;
225 if (p == nullptr)
226 return;
227 }
228 if (q == nullptr)
229 __ibeg_[hi] = p->__next_;
230 else
231 q->__next_ = p->__next_;
232 __c_node* c = p->__c_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000233 --__isz_;
234 if (c != nullptr)
235 c->__remove(p);
Eric Fiselier799b25d2015-03-19 03:20:02 +0000236 free(p);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000237 }
238 }
239}
240
241void
242__libcpp_db::__invalidate_all(void* __c)
243{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000244#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000245 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000246#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000247 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000248 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000249 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
250 __c_node* p = __cbeg_[hc];
251 if (p == nullptr)
252 return;
253 while (p->__c_ != __c)
254 {
255 p = p->__next_;
256 if (p == nullptr)
257 return;
258 }
259 while (p->end_ != p->beg_)
260 {
261 --p->end_;
262 (*p->end_)->__c_ = nullptr;
263 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000264 }
265}
266
267__c_node*
268__libcpp_db::__find_c_and_lock(void* __c) const
269{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000270#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000271 mut().lock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000272#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000273 if (__cend_ == __cbeg_)
274 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000275#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000276 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000277#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000278 return nullptr;
279 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000280 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000281 __c_node* p = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000282 if (p == nullptr)
283 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000284#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000285 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000286#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000287 return nullptr;
288 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000289 while (p->__c_ != __c)
290 {
291 p = p->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000292 if (p == nullptr)
293 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000294#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000295 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000296#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000297 return nullptr;
298 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000299 }
300 return p;
301}
302
Howard Hinnantb399c602011-09-27 23:55:03 +0000303__c_node*
304__libcpp_db::__find_c(void* __c) const
305{
Howard Hinnant28b24882011-12-01 20:21:04 +0000306 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000307 __c_node* p = __cbeg_[hc];
308 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
309 while (p->__c_ != __c)
310 {
311 p = p->__next_;
312 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
313 }
314 return p;
315}
316
Howard Hinnant27e0e772011-09-14 18:33:51 +0000317void
318__libcpp_db::unlock() const
319{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000320#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000321 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000322#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000323}
324
325void
326__libcpp_db::__erase_c(void* __c)
327{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000328#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000329 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000330#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000331 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000332 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000333 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
334 __c_node* p = __cbeg_[hc];
335 if (p == nullptr)
336 return;
337 __c_node* q = nullptr;
338 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
339 while (p->__c_ != __c)
340 {
341 q = p;
342 p = p->__next_;
343 if (p == nullptr)
344 return;
345 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
346 }
347 if (q == nullptr)
348 __cbeg_[hc] = p->__next_;
349 else
350 q->__next_ = p->__next_;
351 while (p->end_ != p->beg_)
352 {
353 --p->end_;
354 (*p->end_)->__c_ = nullptr;
355 }
356 free(p->beg_);
357 free(p);
358 --__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000359 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000360}
361
362void
363__libcpp_db::__iterator_copy(void* __i, const void* __i0)
364{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000365#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000366 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000367#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000368 __i_node* i = __find_iterator(__i);
369 __i_node* i0 = __find_iterator(__i0);
370 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
Howard Hinnant17e485c2013-04-05 17:58:52 +0000371 if (i == nullptr && i0 != nullptr)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000372 i = __insert_iterator(__i);
373 __c_node* c = i != nullptr ? i->__c_ : nullptr;
374 if (c != c0)
375 {
376 if (c != nullptr)
377 c->__remove(i);
378 if (i != nullptr)
379 {
380 i->__c_ = nullptr;
381 if (c0 != nullptr)
382 {
383 i->__c_ = c0;
384 i->__c_->__add(i);
385 }
386 }
387 }
388}
389
390bool
391__libcpp_db::__dereferenceable(const void* __i) const
392{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000393#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000394 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000395#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000396 __i_node* i = __find_iterator(__i);
397 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
398}
399
400bool
401__libcpp_db::__decrementable(const void* __i) const
402{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000403#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000404 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000405#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000406 __i_node* i = __find_iterator(__i);
407 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
408}
409
410bool
411__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
412{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000413#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000414 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000415#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000416 __i_node* i = __find_iterator(__i);
417 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
418}
419
420bool
421__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
422{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000423#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000424 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000425#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000426 __i_node* i = __find_iterator(__i);
427 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
428}
429
430bool
Howard Hinnante6ff0b62013-08-02 00:26:35 +0000431__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
Howard Hinnant27e0e772011-09-14 18:33:51 +0000432{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000433#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000434 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000435#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000436 __i_node* i = __find_iterator(__i);
437 __i_node* j = __find_iterator(__j);
438 __c_node* ci = i != nullptr ? i->__c_ : nullptr;
439 __c_node* cj = j != nullptr ? j->__c_ : nullptr;
Arthur O'Dwyer11eb4b32021-04-20 11:25:37 -0400440 return ci == cj;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000441}
442
443void
444__libcpp_db::swap(void* c1, void* c2)
445{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000446#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000447 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000448#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000449 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000450 __c_node* p1 = __cbeg_[hc];
451 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
452 while (p1->__c_ != c1)
453 {
454 p1 = p1->__next_;
455 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
456 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000457 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000458 __c_node* p2 = __cbeg_[hc];
459 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
460 while (p2->__c_ != c2)
461 {
462 p2 = p2->__next_;
463 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
464 }
465 std::swap(p1->beg_, p2->beg_);
466 std::swap(p1->end_, p2->end_);
467 std::swap(p1->cap_, p2->cap_);
468 for (__i_node** p = p1->beg_; p != p1->end_; ++p)
469 (*p)->__c_ = p1;
470 for (__i_node** p = p2->beg_; p != p2->end_; ++p)
471 (*p)->__c_ = p2;
472}
473
Howard Hinnantc90aa632011-09-16 19:52:23 +0000474void
475__libcpp_db::__insert_i(void* __i)
476{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000477#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantc90aa632011-09-16 19:52:23 +0000478 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000479#endif
Howard Hinnantc90aa632011-09-16 19:52:23 +0000480 __insert_iterator(__i);
481}
482
Howard Hinnantb399c602011-09-27 23:55:03 +0000483void
484__c_node::__add(__i_node* i)
485{
486 if (end_ == cap_)
487 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000488 size_t nc = 2*static_cast<size_t>(cap_ - beg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000489 if (nc == 0)
490 nc = 1;
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000491 __i_node** beg =
492 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
Howard Hinnantb399c602011-09-27 23:55:03 +0000493 if (beg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000494 __throw_bad_alloc();
495
Howard Hinnantb399c602011-09-27 23:55:03 +0000496 if (nc > 1)
497 memcpy(beg, beg_, nc/2*sizeof(__i_node*));
498 free(beg_);
499 beg_ = beg;
500 end_ = beg_ + nc/2;
501 cap_ = beg_ + nc;
502 }
503 *end_++ = i;
504}
505
Howard Hinnant27e0e772011-09-14 18:33:51 +0000506// private api
507
508_LIBCPP_HIDDEN
509__i_node*
510__libcpp_db::__insert_iterator(void* __i)
511{
Howard Hinnant28b24882011-12-01 20:21:04 +0000512 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000513 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000514 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
Louis Dionne71c42dd2019-04-17 16:11:41 +0000515 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000516 if (ibeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000517 __throw_bad_alloc();
518
Howard Hinnant27e0e772011-09-14 18:33:51 +0000519 for (__i_node** p = __ibeg_; p != __iend_; ++p)
520 {
521 __i_node* q = *p;
522 while (q != nullptr)
523 {
524 size_t h = hash<void*>()(q->__i_) % nc;
525 __i_node* r = q->__next_;
526 q->__next_ = ibeg[h];
527 ibeg[h] = q;
528 q = r;
529 }
530 }
531 free(__ibeg_);
532 __ibeg_ = ibeg;
533 __iend_ = __ibeg_ + nc;
534 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000535 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000536 __i_node* p = __ibeg_[hi];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000537 __i_node* r = __ibeg_[hi] =
538 static_cast<__i_node*>(malloc(sizeof(__i_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000539 if (r == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000540 __throw_bad_alloc();
541
Howard Hinnant27e0e772011-09-14 18:33:51 +0000542 ::new(r) __i_node(__i, p, nullptr);
543 ++__isz_;
544 return r;
545}
546
547_LIBCPP_HIDDEN
548__i_node*
549__libcpp_db::__find_iterator(const void* __i) const
550{
551 __i_node* r = nullptr;
552 if (__ibeg_ != __iend_)
553 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000554 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000555 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
556 {
557 if (nd->__i_ == __i)
558 {
559 r = nd;
560 break;
561 }
562 }
563 }
564 return r;
565}
566
567_LIBCPP_HIDDEN
568void
Howard Hinnant27e0e772011-09-14 18:33:51 +0000569__c_node::__remove(__i_node* p)
570{
571 __i_node** r = find(beg_, end_, p);
572 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
573 if (--end_ != r)
Howard Hinnant28b24882011-12-01 20:21:04 +0000574 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000575}
576
577_LIBCPP_END_NAMESPACE_STD