blob: 2e88b859be333b59f1e46cc006699b5713e7f12a [file] [log] [blame]
Howard Hinnant27e0e772011-09-14 18:33:51 +00001//===-------------------------- debug.cpp ---------------------------------===//
2//
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"
16#include "mutex"
17
18_LIBCPP_BEGIN_NAMESPACE_STD
19
Eric Fiselierfb825432016-12-28 04:58:52 +000020static std::string make_what_str(__libcpp_debug_info const& info) {
21 string msg = info.__file_;
22 msg += ":" + to_string(info.__line_) + ": _LIBCPP_ASSERT '";
23 msg += info.__pred_;
24 msg += "' failed. ";
25 msg += info.__msg_;
26 return msg;
27}
28
29_LIBCPP_SAFE_STATIC __libcpp_debug_function_type
30 __libcpp_debug_function = __libcpp_abort_debug_function;
31
32bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
33 __libcpp_debug_function = __func;
34 return true;
35}
36
37_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
38 std::fprintf(stderr, "%s\n", make_what_str(info).c_str());
39 std::abort();
40}
41
42_LIBCPP_NORETURN void __libcpp_throw_debug_function(__libcpp_debug_info const& info) {
Eric Fiselierb18682d2016-12-28 05:20:27 +000043#ifndef _LIBCPP_NO_EXCEPTIONS
Eric Fiselierfb825432016-12-28 04:58:52 +000044 throw __libcpp_debug_exception(info);
Eric Fiselierb18682d2016-12-28 05:20:27 +000045#else
46 __libcpp_abort_debug_function(info);
47#endif
Eric Fiselierfb825432016-12-28 04:58:52 +000048}
49
50struct __libcpp_debug_exception::__libcpp_debug_exception_imp {
51 __libcpp_debug_info __info_;
52 std::string __what_str_;
53};
54
55__libcpp_debug_exception::__libcpp_debug_exception() _NOEXCEPT
56 : __imp_(nullptr) {
57}
58
59__libcpp_debug_exception::__libcpp_debug_exception(
60 __libcpp_debug_info const& info) : __imp_(new __libcpp_debug_exception_imp)
61{
62 __imp_->__info_ = info;
63 __imp_->__what_str_ = make_what_str(info);
64}
65__libcpp_debug_exception::__libcpp_debug_exception(
66 __libcpp_debug_exception const& other) : __imp_(nullptr) {
67 if (other.__imp_)
68 __imp_ = new __libcpp_debug_exception_imp(*other.__imp_);
69}
70
71__libcpp_debug_exception::~__libcpp_debug_exception() _NOEXCEPT {
72 if (__imp_)
73 delete __imp_;
74}
75
76const char* __libcpp_debug_exception::what() const _NOEXCEPT {
77 if (__imp_)
78 return __imp_->__what_str_.c_str();
79 return "__libcpp_debug_exception";
80}
81
Howard Hinnant8331b762013-03-06 23:30:19 +000082_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000083__libcpp_db*
84__get_db()
85{
86 static __libcpp_db db;
87 return &db;
Howard Hinnant434ebf72012-12-27 18:46:00 +000088}
Howard Hinnant27e0e772011-09-14 18:33:51 +000089
Howard Hinnant8331b762013-03-06 23:30:19 +000090_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000091const __libcpp_db*
92__get_const_db()
93{
94 return __get_db();
95}
96
97namespace
98{
99
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000100#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000101typedef mutex mutex_type;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000102typedef lock_guard<mutex_type> WLock;
103typedef lock_guard<mutex_type> RLock;
104
105mutex_type&
106mut()
107{
108 static mutex_type m;
109 return m;
110}
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000111#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000112
113} // unnamed namespace
114
115__i_node::~__i_node()
116{
117 if (__next_)
118 {
119 __next_->~__i_node();
120 free(__next_);
121 }
122}
123
124__c_node::~__c_node()
125{
126 free(beg_);
127 if (__next_)
128 {
129 __next_->~__c_node();
130 free(__next_);
131 }
132}
133
134__libcpp_db::__libcpp_db()
135 : __cbeg_(nullptr),
136 __cend_(nullptr),
137 __csz_(0),
138 __ibeg_(nullptr),
139 __iend_(nullptr),
140 __isz_(0)
141{
142}
143
144__libcpp_db::~__libcpp_db()
145{
146 if (__cbeg_)
147 {
148 for (__c_node** p = __cbeg_; p != __cend_; ++p)
149 {
150 if (*p != nullptr)
151 {
152 (*p)->~__c_node();
153 free(*p);
154 }
155 }
156 free(__cbeg_);
157 }
158 if (__ibeg_)
159 {
160 for (__i_node** p = __ibeg_; p != __iend_; ++p)
161 {
162 if (*p != nullptr)
163 {
164 (*p)->~__i_node();
165 free(*p);
166 }
167 }
168 free(__ibeg_);
169 }
170}
171
172void*
173__libcpp_db::__find_c_from_i(void* __i) const
174{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000175#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000176 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000177#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000178 __i_node* i = __find_iterator(__i);
Howard Hinnant17e485c2013-04-05 17:58:52 +0000179 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
Howard Hinnantc90aa632011-09-16 19:52:23 +0000180 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000181}
182
183void
184__libcpp_db::__insert_ic(void* __i, const void* __c)
185{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000186#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000187 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000188#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000189 if (__cbeg_ == __cend_)
190 return;
Howard Hinnant28b24882011-12-01 20:21:04 +0000191 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000192 __c_node* c = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000193 if (c == nullptr)
194 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000195 while (c->__c_ != __c)
196 {
197 c = c->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000198 if (c == nullptr)
199 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000200 }
Howard Hinnant8ea98242013-08-23 17:37:05 +0000201 __i_node* i = __insert_iterator(__i);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000202 c->__add(i);
203 i->__c_ = c;
204}
205
206__c_node*
207__libcpp_db::__insert_c(void* __c)
208{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000209#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000210 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000211#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000212 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000213 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000214 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000215 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000216 if (cbeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000217 __throw_bad_alloc();
218
Howard Hinnant27e0e772011-09-14 18:33:51 +0000219 for (__c_node** p = __cbeg_; p != __cend_; ++p)
220 {
221 __c_node* q = *p;
222 while (q != nullptr)
223 {
224 size_t h = hash<void*>()(q->__c_) % nc;
225 __c_node* r = q->__next_;
226 q->__next_ = cbeg[h];
227 cbeg[h] = q;
228 q = r;
229 }
230 }
231 free(__cbeg_);
232 __cbeg_ = cbeg;
233 __cend_ = __cbeg_ + nc;
234 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000235 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000236 __c_node* p = __cbeg_[hc];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000237 __c_node* r = __cbeg_[hc] =
238 static_cast<__c_node*>(malloc(sizeof(__c_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000239 if (__cbeg_[hc] == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000240 __throw_bad_alloc();
241
Howard Hinnant27e0e772011-09-14 18:33:51 +0000242 r->__c_ = __c;
243 r->__next_ = p;
244 ++__csz_;
245 return r;
246}
247
248void
249__libcpp_db::__erase_i(void* __i)
250{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000251#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000252 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000253#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000254 if (__ibeg_ != __iend_)
255 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000256 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000257 __i_node* p = __ibeg_[hi];
258 if (p != nullptr)
259 {
260 __i_node* q = nullptr;
261 while (p->__i_ != __i)
262 {
263 q = p;
264 p = p->__next_;
265 if (p == nullptr)
266 return;
267 }
268 if (q == nullptr)
269 __ibeg_[hi] = p->__next_;
270 else
271 q->__next_ = p->__next_;
272 __c_node* c = p->__c_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000273 --__isz_;
274 if (c != nullptr)
275 c->__remove(p);
Eric Fiselier799b25d2015-03-19 03:20:02 +0000276 free(p);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000277 }
278 }
279}
280
281void
282__libcpp_db::__invalidate_all(void* __c)
283{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000284#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000285 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000286#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000287 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000288 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000289 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
290 __c_node* p = __cbeg_[hc];
291 if (p == nullptr)
292 return;
293 while (p->__c_ != __c)
294 {
295 p = p->__next_;
296 if (p == nullptr)
297 return;
298 }
299 while (p->end_ != p->beg_)
300 {
301 --p->end_;
302 (*p->end_)->__c_ = nullptr;
303 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000304 }
305}
306
307__c_node*
308__libcpp_db::__find_c_and_lock(void* __c) const
309{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000310#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000311 mut().lock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000312#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000313 if (__cend_ == __cbeg_)
314 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000315#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000316 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000317#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000318 return nullptr;
319 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000320 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000321 __c_node* p = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000322 if (p == nullptr)
323 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000324#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000325 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000326#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000327 return nullptr;
328 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000329 while (p->__c_ != __c)
330 {
331 p = p->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000332 if (p == nullptr)
333 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000334#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000335 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000336#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000337 return nullptr;
338 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000339 }
340 return p;
341}
342
Howard Hinnantb399c602011-09-27 23:55:03 +0000343__c_node*
344__libcpp_db::__find_c(void* __c) const
345{
Howard Hinnant28b24882011-12-01 20:21:04 +0000346 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000347 __c_node* p = __cbeg_[hc];
348 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
349 while (p->__c_ != __c)
350 {
351 p = p->__next_;
352 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
353 }
354 return p;
355}
356
Howard Hinnant27e0e772011-09-14 18:33:51 +0000357void
358__libcpp_db::unlock() const
359{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000360#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000361 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000362#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000363}
364
365void
366__libcpp_db::__erase_c(void* __c)
367{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000368#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000369 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000370#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000371 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000372 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000373 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
374 __c_node* p = __cbeg_[hc];
375 if (p == nullptr)
376 return;
377 __c_node* q = nullptr;
378 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
379 while (p->__c_ != __c)
380 {
381 q = p;
382 p = p->__next_;
383 if (p == nullptr)
384 return;
385 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
386 }
387 if (q == nullptr)
388 __cbeg_[hc] = p->__next_;
389 else
390 q->__next_ = p->__next_;
391 while (p->end_ != p->beg_)
392 {
393 --p->end_;
394 (*p->end_)->__c_ = nullptr;
395 }
396 free(p->beg_);
397 free(p);
398 --__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000399 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000400}
401
402void
403__libcpp_db::__iterator_copy(void* __i, const void* __i0)
404{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000405#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000406 WLock _(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 __i_node* i0 = __find_iterator(__i0);
410 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
Howard Hinnant17e485c2013-04-05 17:58:52 +0000411 if (i == nullptr && i0 != nullptr)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000412 i = __insert_iterator(__i);
413 __c_node* c = i != nullptr ? i->__c_ : nullptr;
414 if (c != c0)
415 {
416 if (c != nullptr)
417 c->__remove(i);
418 if (i != nullptr)
419 {
420 i->__c_ = nullptr;
421 if (c0 != nullptr)
422 {
423 i->__c_ = c0;
424 i->__c_->__add(i);
425 }
426 }
427 }
428}
429
430bool
431__libcpp_db::__dereferenceable(const void* __i) const
432{
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 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
438}
439
440bool
441__libcpp_db::__decrementable(const void* __i) const
442{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000443#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000444 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000445#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000446 __i_node* i = __find_iterator(__i);
447 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
448}
449
450bool
451__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
452{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000453#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000454 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000455#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000456 __i_node* i = __find_iterator(__i);
457 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
458}
459
460bool
461__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
462{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000463#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000464 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000465#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000466 __i_node* i = __find_iterator(__i);
467 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
468}
469
470bool
Howard Hinnante6ff0b62013-08-02 00:26:35 +0000471__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
Howard Hinnant27e0e772011-09-14 18:33:51 +0000472{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000473#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000474 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000475#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000476 __i_node* i = __find_iterator(__i);
477 __i_node* j = __find_iterator(__j);
478 __c_node* ci = i != nullptr ? i->__c_ : nullptr;
479 __c_node* cj = j != nullptr ? j->__c_ : nullptr;
480 return ci != nullptr && ci == cj;
481}
482
483void
484__libcpp_db::swap(void* c1, void* c2)
485{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000486#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000487 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000488#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000489 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000490 __c_node* p1 = __cbeg_[hc];
491 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
492 while (p1->__c_ != c1)
493 {
494 p1 = p1->__next_;
495 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
496 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000497 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000498 __c_node* p2 = __cbeg_[hc];
499 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
500 while (p2->__c_ != c2)
501 {
502 p2 = p2->__next_;
503 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
504 }
505 std::swap(p1->beg_, p2->beg_);
506 std::swap(p1->end_, p2->end_);
507 std::swap(p1->cap_, p2->cap_);
508 for (__i_node** p = p1->beg_; p != p1->end_; ++p)
509 (*p)->__c_ = p1;
510 for (__i_node** p = p2->beg_; p != p2->end_; ++p)
511 (*p)->__c_ = p2;
512}
513
Howard Hinnantc90aa632011-09-16 19:52:23 +0000514void
515__libcpp_db::__insert_i(void* __i)
516{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000517#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantc90aa632011-09-16 19:52:23 +0000518 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000519#endif
Howard Hinnantc90aa632011-09-16 19:52:23 +0000520 __insert_iterator(__i);
521}
522
Howard Hinnantb399c602011-09-27 23:55:03 +0000523void
524__c_node::__add(__i_node* i)
525{
526 if (end_ == cap_)
527 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000528 size_t nc = 2*static_cast<size_t>(cap_ - beg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000529 if (nc == 0)
530 nc = 1;
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000531 __i_node** beg =
532 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
Howard Hinnantb399c602011-09-27 23:55:03 +0000533 if (beg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000534 __throw_bad_alloc();
535
Howard Hinnantb399c602011-09-27 23:55:03 +0000536 if (nc > 1)
537 memcpy(beg, beg_, nc/2*sizeof(__i_node*));
538 free(beg_);
539 beg_ = beg;
540 end_ = beg_ + nc/2;
541 cap_ = beg_ + nc;
542 }
543 *end_++ = i;
544}
545
Howard Hinnant27e0e772011-09-14 18:33:51 +0000546// private api
547
548_LIBCPP_HIDDEN
549__i_node*
550__libcpp_db::__insert_iterator(void* __i)
551{
Howard Hinnant28b24882011-12-01 20:21:04 +0000552 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000553 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000554 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000555 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000556 if (ibeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000557 __throw_bad_alloc();
558
Howard Hinnant27e0e772011-09-14 18:33:51 +0000559 for (__i_node** p = __ibeg_; p != __iend_; ++p)
560 {
561 __i_node* q = *p;
562 while (q != nullptr)
563 {
564 size_t h = hash<void*>()(q->__i_) % nc;
565 __i_node* r = q->__next_;
566 q->__next_ = ibeg[h];
567 ibeg[h] = q;
568 q = r;
569 }
570 }
571 free(__ibeg_);
572 __ibeg_ = ibeg;
573 __iend_ = __ibeg_ + nc;
574 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000575 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000576 __i_node* p = __ibeg_[hi];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000577 __i_node* r = __ibeg_[hi] =
578 static_cast<__i_node*>(malloc(sizeof(__i_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000579 if (r == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000580 __throw_bad_alloc();
581
Howard Hinnant27e0e772011-09-14 18:33:51 +0000582 ::new(r) __i_node(__i, p, nullptr);
583 ++__isz_;
584 return r;
585}
586
587_LIBCPP_HIDDEN
588__i_node*
589__libcpp_db::__find_iterator(const void* __i) const
590{
591 __i_node* r = nullptr;
592 if (__ibeg_ != __iend_)
593 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000594 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000595 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
596 {
597 if (nd->__i_ == __i)
598 {
599 r = nd;
600 break;
601 }
602 }
603 }
604 return r;
605}
606
607_LIBCPP_HIDDEN
608void
Howard Hinnant27e0e772011-09-14 18:33:51 +0000609__c_node::__remove(__i_node* p)
610{
611 __i_node** r = find(beg_, end_, p);
612 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
613 if (--end_ != r)
Howard Hinnant28b24882011-12-01 20:21:04 +0000614 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000615}
616
617_LIBCPP_END_NAMESPACE_STD