blob: 28a1f70a59b02a2f8a784d602b6cf91ca3c5bc84 [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
Eric Fiselieraed4eab2019-03-05 02:10:31 +0000206void
207__libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000208{
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];
Eric Fiselieraed4eab2019-03-05 02:10:31 +0000237 void *buf = malloc(sizeof(__c_node));
238 if (buf == nullptr)
239 __throw_bad_alloc();
240 __cbeg_[hc] = __fn(buf, __c, p);
Marshall Clow8fea1612016-08-25 15:09:01 +0000241
Howard Hinnant27e0e772011-09-14 18:33:51 +0000242 ++__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000243}
244
245void
246__libcpp_db::__erase_i(void* __i)
247{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000248#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000249 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000250#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000251 if (__ibeg_ != __iend_)
252 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000253 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000254 __i_node* p = __ibeg_[hi];
255 if (p != nullptr)
256 {
257 __i_node* q = nullptr;
258 while (p->__i_ != __i)
259 {
260 q = p;
261 p = p->__next_;
262 if (p == nullptr)
263 return;
264 }
265 if (q == nullptr)
266 __ibeg_[hi] = p->__next_;
267 else
268 q->__next_ = p->__next_;
269 __c_node* c = p->__c_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000270 --__isz_;
271 if (c != nullptr)
272 c->__remove(p);
Eric Fiselier799b25d2015-03-19 03:20:02 +0000273 free(p);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000274 }
275 }
276}
277
278void
279__libcpp_db::__invalidate_all(void* __c)
280{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000281#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000282 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000283#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000284 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000285 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000286 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
287 __c_node* p = __cbeg_[hc];
288 if (p == nullptr)
289 return;
290 while (p->__c_ != __c)
291 {
292 p = p->__next_;
293 if (p == nullptr)
294 return;
295 }
296 while (p->end_ != p->beg_)
297 {
298 --p->end_;
299 (*p->end_)->__c_ = nullptr;
300 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000301 }
302}
303
304__c_node*
305__libcpp_db::__find_c_and_lock(void* __c) const
306{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000307#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000308 mut().lock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000309#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000310 if (__cend_ == __cbeg_)
311 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000312#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000313 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000314#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000315 return nullptr;
316 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000317 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000318 __c_node* p = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000319 if (p == nullptr)
320 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000321#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000322 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000323#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000324 return nullptr;
325 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000326 while (p->__c_ != __c)
327 {
328 p = p->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000329 if (p == nullptr)
330 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000331#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000332 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000333#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000334 return nullptr;
335 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000336 }
337 return p;
338}
339
Howard Hinnantb399c602011-09-27 23:55:03 +0000340__c_node*
341__libcpp_db::__find_c(void* __c) const
342{
Howard Hinnant28b24882011-12-01 20:21:04 +0000343 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000344 __c_node* p = __cbeg_[hc];
345 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
346 while (p->__c_ != __c)
347 {
348 p = p->__next_;
349 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
350 }
351 return p;
352}
353
Howard Hinnant27e0e772011-09-14 18:33:51 +0000354void
355__libcpp_db::unlock() const
356{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000357#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000358 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000359#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000360}
361
362void
363__libcpp_db::__erase_c(void* __c)
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 Hinnant8ea98242013-08-23 17:37:05 +0000368 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000369 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000370 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
371 __c_node* p = __cbeg_[hc];
372 if (p == nullptr)
373 return;
374 __c_node* q = nullptr;
375 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
376 while (p->__c_ != __c)
377 {
378 q = p;
379 p = p->__next_;
380 if (p == nullptr)
381 return;
382 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
383 }
384 if (q == nullptr)
385 __cbeg_[hc] = p->__next_;
386 else
387 q->__next_ = p->__next_;
388 while (p->end_ != p->beg_)
389 {
390 --p->end_;
391 (*p->end_)->__c_ = nullptr;
392 }
393 free(p->beg_);
394 free(p);
395 --__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000396 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000397}
398
399void
400__libcpp_db::__iterator_copy(void* __i, const void* __i0)
401{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000402#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000403 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000404#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000405 __i_node* i = __find_iterator(__i);
406 __i_node* i0 = __find_iterator(__i0);
407 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
Howard Hinnant17e485c2013-04-05 17:58:52 +0000408 if (i == nullptr && i0 != nullptr)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000409 i = __insert_iterator(__i);
410 __c_node* c = i != nullptr ? i->__c_ : nullptr;
411 if (c != c0)
412 {
413 if (c != nullptr)
414 c->__remove(i);
415 if (i != nullptr)
416 {
417 i->__c_ = nullptr;
418 if (c0 != nullptr)
419 {
420 i->__c_ = c0;
421 i->__c_->__add(i);
422 }
423 }
424 }
425}
426
427bool
428__libcpp_db::__dereferenceable(const void* __i) const
429{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000430#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000431 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000432#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000433 __i_node* i = __find_iterator(__i);
434 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
435}
436
437bool
438__libcpp_db::__decrementable(const void* __i) const
439{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000440#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000441 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000442#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000443 __i_node* i = __find_iterator(__i);
444 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
445}
446
447bool
448__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
449{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000450#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000451 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000452#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000453 __i_node* i = __find_iterator(__i);
454 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
455}
456
457bool
458__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
459{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000460#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000461 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000462#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000463 __i_node* i = __find_iterator(__i);
464 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
465}
466
467bool
Howard Hinnante6ff0b62013-08-02 00:26:35 +0000468__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
Howard Hinnant27e0e772011-09-14 18:33:51 +0000469{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000470#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000471 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000472#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000473 __i_node* i = __find_iterator(__i);
474 __i_node* j = __find_iterator(__j);
475 __c_node* ci = i != nullptr ? i->__c_ : nullptr;
476 __c_node* cj = j != nullptr ? j->__c_ : nullptr;
477 return ci != nullptr && ci == cj;
478}
479
480void
481__libcpp_db::swap(void* c1, void* c2)
482{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000483#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000484 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000485#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000486 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000487 __c_node* p1 = __cbeg_[hc];
488 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
489 while (p1->__c_ != c1)
490 {
491 p1 = p1->__next_;
492 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
493 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000494 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000495 __c_node* p2 = __cbeg_[hc];
496 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
497 while (p2->__c_ != c2)
498 {
499 p2 = p2->__next_;
500 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
501 }
502 std::swap(p1->beg_, p2->beg_);
503 std::swap(p1->end_, p2->end_);
504 std::swap(p1->cap_, p2->cap_);
505 for (__i_node** p = p1->beg_; p != p1->end_; ++p)
506 (*p)->__c_ = p1;
507 for (__i_node** p = p2->beg_; p != p2->end_; ++p)
508 (*p)->__c_ = p2;
509}
510
Howard Hinnantc90aa632011-09-16 19:52:23 +0000511void
512__libcpp_db::__insert_i(void* __i)
513{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000514#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantc90aa632011-09-16 19:52:23 +0000515 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000516#endif
Howard Hinnantc90aa632011-09-16 19:52:23 +0000517 __insert_iterator(__i);
518}
519
Howard Hinnantb399c602011-09-27 23:55:03 +0000520void
521__c_node::__add(__i_node* i)
522{
523 if (end_ == cap_)
524 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000525 size_t nc = 2*static_cast<size_t>(cap_ - beg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000526 if (nc == 0)
527 nc = 1;
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000528 __i_node** beg =
529 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
Howard Hinnantb399c602011-09-27 23:55:03 +0000530 if (beg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000531 __throw_bad_alloc();
532
Howard Hinnantb399c602011-09-27 23:55:03 +0000533 if (nc > 1)
534 memcpy(beg, beg_, nc/2*sizeof(__i_node*));
535 free(beg_);
536 beg_ = beg;
537 end_ = beg_ + nc/2;
538 cap_ = beg_ + nc;
539 }
540 *end_++ = i;
541}
542
Howard Hinnant27e0e772011-09-14 18:33:51 +0000543// private api
544
545_LIBCPP_HIDDEN
546__i_node*
547__libcpp_db::__insert_iterator(void* __i)
548{
Howard Hinnant28b24882011-12-01 20:21:04 +0000549 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000550 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000551 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000552 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000553 if (ibeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000554 __throw_bad_alloc();
555
Howard Hinnant27e0e772011-09-14 18:33:51 +0000556 for (__i_node** p = __ibeg_; p != __iend_; ++p)
557 {
558 __i_node* q = *p;
559 while (q != nullptr)
560 {
561 size_t h = hash<void*>()(q->__i_) % nc;
562 __i_node* r = q->__next_;
563 q->__next_ = ibeg[h];
564 ibeg[h] = q;
565 q = r;
566 }
567 }
568 free(__ibeg_);
569 __ibeg_ = ibeg;
570 __iend_ = __ibeg_ + nc;
571 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000572 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000573 __i_node* p = __ibeg_[hi];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000574 __i_node* r = __ibeg_[hi] =
575 static_cast<__i_node*>(malloc(sizeof(__i_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000576 if (r == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000577 __throw_bad_alloc();
578
Howard Hinnant27e0e772011-09-14 18:33:51 +0000579 ::new(r) __i_node(__i, p, nullptr);
580 ++__isz_;
581 return r;
582}
583
584_LIBCPP_HIDDEN
585__i_node*
586__libcpp_db::__find_iterator(const void* __i) const
587{
588 __i_node* r = nullptr;
589 if (__ibeg_ != __iend_)
590 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000591 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000592 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
593 {
594 if (nd->__i_ == __i)
595 {
596 r = nd;
597 break;
598 }
599 }
600 }
601 return r;
602}
603
604_LIBCPP_HIDDEN
605void
Howard Hinnant27e0e772011-09-14 18:33:51 +0000606__c_node::__remove(__i_node* p)
607{
608 __i_node** r = find(beg_, end_, p);
609 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
610 if (--end_ != r)
Howard Hinnant28b24882011-12-01 20:21:04 +0000611 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000612}
613
614_LIBCPP_END_NAMESPACE_STD