blob: fe27dc82ca615ba16327b18f49d75db91c96d661 [file] [log] [blame]
Howard Hinnant27e0e772011-09-14 18:33:51 +00001//===-------------------------- debug.cpp ---------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Howard Hinnanta47c6d52011-09-16 17:29:17 +000010#include "__config"
Howard Hinnant27e0e772011-09-14 18:33:51 +000011#include "__debug"
12#include "functional"
13#include "algorithm"
Eric Fiselierfb825432016-12-28 04:58:52 +000014#include "string"
15#include "cstdio"
Howard Hinnant27e0e772011-09-14 18:33:51 +000016#include "__hash_table"
17#include "mutex"
18
19_LIBCPP_BEGIN_NAMESPACE_STD
20
Eric Fiselierfb825432016-12-28 04:58:52 +000021static std::string make_what_str(__libcpp_debug_info const& info) {
22 string msg = info.__file_;
23 msg += ":" + to_string(info.__line_) + ": _LIBCPP_ASSERT '";
24 msg += info.__pred_;
25 msg += "' failed. ";
26 msg += info.__msg_;
27 return msg;
28}
29
30_LIBCPP_SAFE_STATIC __libcpp_debug_function_type
31 __libcpp_debug_function = __libcpp_abort_debug_function;
32
33bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
34 __libcpp_debug_function = __func;
35 return true;
36}
37
38_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
39 std::fprintf(stderr, "%s\n", make_what_str(info).c_str());
40 std::abort();
41}
42
43_LIBCPP_NORETURN void __libcpp_throw_debug_function(__libcpp_debug_info const& info) {
44 throw __libcpp_debug_exception(info);
45}
46
47struct __libcpp_debug_exception::__libcpp_debug_exception_imp {
48 __libcpp_debug_info __info_;
49 std::string __what_str_;
50};
51
52__libcpp_debug_exception::__libcpp_debug_exception() _NOEXCEPT
53 : __imp_(nullptr) {
54}
55
56__libcpp_debug_exception::__libcpp_debug_exception(
57 __libcpp_debug_info const& info) : __imp_(new __libcpp_debug_exception_imp)
58{
59 __imp_->__info_ = info;
60 __imp_->__what_str_ = make_what_str(info);
61}
62__libcpp_debug_exception::__libcpp_debug_exception(
63 __libcpp_debug_exception const& other) : __imp_(nullptr) {
64 if (other.__imp_)
65 __imp_ = new __libcpp_debug_exception_imp(*other.__imp_);
66}
67
68__libcpp_debug_exception::~__libcpp_debug_exception() _NOEXCEPT {
69 if (__imp_)
70 delete __imp_;
71}
72
73const char* __libcpp_debug_exception::what() const _NOEXCEPT {
74 if (__imp_)
75 return __imp_->__what_str_.c_str();
76 return "__libcpp_debug_exception";
77}
78
Howard Hinnant8331b762013-03-06 23:30:19 +000079_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000080__libcpp_db*
81__get_db()
82{
83 static __libcpp_db db;
84 return &db;
Howard Hinnant434ebf72012-12-27 18:46:00 +000085}
Howard Hinnant27e0e772011-09-14 18:33:51 +000086
Howard Hinnant8331b762013-03-06 23:30:19 +000087_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000088const __libcpp_db*
89__get_const_db()
90{
91 return __get_db();
92}
93
94namespace
95{
96
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000097#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +000098typedef mutex mutex_type;
Howard Hinnant27e0e772011-09-14 18:33:51 +000099typedef lock_guard<mutex_type> WLock;
100typedef lock_guard<mutex_type> RLock;
101
102mutex_type&
103mut()
104{
105 static mutex_type m;
106 return m;
107}
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000108#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000109
110} // unnamed namespace
111
112__i_node::~__i_node()
113{
114 if (__next_)
115 {
116 __next_->~__i_node();
117 free(__next_);
118 }
119}
120
121__c_node::~__c_node()
122{
123 free(beg_);
124 if (__next_)
125 {
126 __next_->~__c_node();
127 free(__next_);
128 }
129}
130
131__libcpp_db::__libcpp_db()
132 : __cbeg_(nullptr),
133 __cend_(nullptr),
134 __csz_(0),
135 __ibeg_(nullptr),
136 __iend_(nullptr),
137 __isz_(0)
138{
139}
140
141__libcpp_db::~__libcpp_db()
142{
143 if (__cbeg_)
144 {
145 for (__c_node** p = __cbeg_; p != __cend_; ++p)
146 {
147 if (*p != nullptr)
148 {
149 (*p)->~__c_node();
150 free(*p);
151 }
152 }
153 free(__cbeg_);
154 }
155 if (__ibeg_)
156 {
157 for (__i_node** p = __ibeg_; p != __iend_; ++p)
158 {
159 if (*p != nullptr)
160 {
161 (*p)->~__i_node();
162 free(*p);
163 }
164 }
165 free(__ibeg_);
166 }
167}
168
169void*
170__libcpp_db::__find_c_from_i(void* __i) const
171{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000172#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000173 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000174#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000175 __i_node* i = __find_iterator(__i);
Howard Hinnant17e485c2013-04-05 17:58:52 +0000176 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
Howard Hinnantc90aa632011-09-16 19:52:23 +0000177 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000178}
179
180void
181__libcpp_db::__insert_ic(void* __i, const void* __c)
182{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000183#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000184 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000185#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000186 if (__cbeg_ == __cend_)
187 return;
Howard Hinnant28b24882011-12-01 20:21:04 +0000188 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000189 __c_node* c = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000190 if (c == nullptr)
191 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000192 while (c->__c_ != __c)
193 {
194 c = c->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000195 if (c == nullptr)
196 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000197 }
Howard Hinnant8ea98242013-08-23 17:37:05 +0000198 __i_node* i = __insert_iterator(__i);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000199 c->__add(i);
200 i->__c_ = c;
201}
202
203__c_node*
204__libcpp_db::__insert_c(void* __c)
205{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000206#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000207 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000208#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000209 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000210 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000211 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000212 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000213 if (cbeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000214 __throw_bad_alloc();
215
Howard Hinnant27e0e772011-09-14 18:33:51 +0000216 for (__c_node** p = __cbeg_; p != __cend_; ++p)
217 {
218 __c_node* q = *p;
219 while (q != nullptr)
220 {
221 size_t h = hash<void*>()(q->__c_) % nc;
222 __c_node* r = q->__next_;
223 q->__next_ = cbeg[h];
224 cbeg[h] = q;
225 q = r;
226 }
227 }
228 free(__cbeg_);
229 __cbeg_ = cbeg;
230 __cend_ = __cbeg_ + nc;
231 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000232 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000233 __c_node* p = __cbeg_[hc];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000234 __c_node* r = __cbeg_[hc] =
235 static_cast<__c_node*>(malloc(sizeof(__c_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000236 if (__cbeg_[hc] == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000237 __throw_bad_alloc();
238
Howard Hinnant27e0e772011-09-14 18:33:51 +0000239 r->__c_ = __c;
240 r->__next_ = p;
241 ++__csz_;
242 return r;
243}
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