blob: f2fc1ceb495a8e56163109ad598b25788c47db8b [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) {
Eric Fiselierb18682d2016-12-28 05:20:27 +000044#ifndef _LIBCPP_NO_EXCEPTIONS
Eric Fiselierfb825432016-12-28 04:58:52 +000045 throw __libcpp_debug_exception(info);
Eric Fiselierb18682d2016-12-28 05:20:27 +000046#else
47 __libcpp_abort_debug_function(info);
48#endif
Eric Fiselierfb825432016-12-28 04:58:52 +000049}
50
51struct __libcpp_debug_exception::__libcpp_debug_exception_imp {
52 __libcpp_debug_info __info_;
53 std::string __what_str_;
54};
55
56__libcpp_debug_exception::__libcpp_debug_exception() _NOEXCEPT
57 : __imp_(nullptr) {
58}
59
60__libcpp_debug_exception::__libcpp_debug_exception(
61 __libcpp_debug_info const& info) : __imp_(new __libcpp_debug_exception_imp)
62{
63 __imp_->__info_ = info;
64 __imp_->__what_str_ = make_what_str(info);
65}
66__libcpp_debug_exception::__libcpp_debug_exception(
67 __libcpp_debug_exception const& other) : __imp_(nullptr) {
68 if (other.__imp_)
69 __imp_ = new __libcpp_debug_exception_imp(*other.__imp_);
70}
71
72__libcpp_debug_exception::~__libcpp_debug_exception() _NOEXCEPT {
73 if (__imp_)
74 delete __imp_;
75}
76
77const char* __libcpp_debug_exception::what() const _NOEXCEPT {
78 if (__imp_)
79 return __imp_->__what_str_.c_str();
80 return "__libcpp_debug_exception";
81}
82
Howard Hinnant8331b762013-03-06 23:30:19 +000083_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000084__libcpp_db*
85__get_db()
86{
87 static __libcpp_db db;
88 return &db;
Howard Hinnant434ebf72012-12-27 18:46:00 +000089}
Howard Hinnant27e0e772011-09-14 18:33:51 +000090
Howard Hinnant8331b762013-03-06 23:30:19 +000091_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000092const __libcpp_db*
93__get_const_db()
94{
95 return __get_db();
96}
97
98namespace
99{
100
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000101#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000102typedef mutex mutex_type;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000103typedef lock_guard<mutex_type> WLock;
104typedef lock_guard<mutex_type> RLock;
105
106mutex_type&
107mut()
108{
109 static mutex_type m;
110 return m;
111}
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000112#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000113
114} // unnamed namespace
115
116__i_node::~__i_node()
117{
118 if (__next_)
119 {
120 __next_->~__i_node();
121 free(__next_);
122 }
123}
124
125__c_node::~__c_node()
126{
127 free(beg_);
128 if (__next_)
129 {
130 __next_->~__c_node();
131 free(__next_);
132 }
133}
134
135__libcpp_db::__libcpp_db()
136 : __cbeg_(nullptr),
137 __cend_(nullptr),
138 __csz_(0),
139 __ibeg_(nullptr),
140 __iend_(nullptr),
141 __isz_(0)
142{
143}
144
145__libcpp_db::~__libcpp_db()
146{
147 if (__cbeg_)
148 {
149 for (__c_node** p = __cbeg_; p != __cend_; ++p)
150 {
151 if (*p != nullptr)
152 {
153 (*p)->~__c_node();
154 free(*p);
155 }
156 }
157 free(__cbeg_);
158 }
159 if (__ibeg_)
160 {
161 for (__i_node** p = __ibeg_; p != __iend_; ++p)
162 {
163 if (*p != nullptr)
164 {
165 (*p)->~__i_node();
166 free(*p);
167 }
168 }
169 free(__ibeg_);
170 }
171}
172
173void*
174__libcpp_db::__find_c_from_i(void* __i) const
175{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000176#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000177 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000178#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000179 __i_node* i = __find_iterator(__i);
Howard Hinnant17e485c2013-04-05 17:58:52 +0000180 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
Howard Hinnantc90aa632011-09-16 19:52:23 +0000181 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000182}
183
184void
185__libcpp_db::__insert_ic(void* __i, const void* __c)
186{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000187#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000188 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000189#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000190 if (__cbeg_ == __cend_)
191 return;
Howard Hinnant28b24882011-12-01 20:21:04 +0000192 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000193 __c_node* c = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000194 if (c == nullptr)
195 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000196 while (c->__c_ != __c)
197 {
198 c = c->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000199 if (c == nullptr)
200 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000201 }
Howard Hinnant8ea98242013-08-23 17:37:05 +0000202 __i_node* i = __insert_iterator(__i);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000203 c->__add(i);
204 i->__c_ = c;
205}
206
207__c_node*
208__libcpp_db::__insert_c(void* __c)
209{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000210#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000211 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000212#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000213 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000214 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000215 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000216 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000217 if (cbeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000218 __throw_bad_alloc();
219
Howard Hinnant27e0e772011-09-14 18:33:51 +0000220 for (__c_node** p = __cbeg_; p != __cend_; ++p)
221 {
222 __c_node* q = *p;
223 while (q != nullptr)
224 {
225 size_t h = hash<void*>()(q->__c_) % nc;
226 __c_node* r = q->__next_;
227 q->__next_ = cbeg[h];
228 cbeg[h] = q;
229 q = r;
230 }
231 }
232 free(__cbeg_);
233 __cbeg_ = cbeg;
234 __cend_ = __cbeg_ + nc;
235 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000236 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000237 __c_node* p = __cbeg_[hc];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000238 __c_node* r = __cbeg_[hc] =
239 static_cast<__c_node*>(malloc(sizeof(__c_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000240 if (__cbeg_[hc] == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000241 __throw_bad_alloc();
242
Howard Hinnant27e0e772011-09-14 18:33:51 +0000243 r->__c_ = __c;
244 r->__next_ = p;
245 ++__csz_;
246 return r;
247}
248
249void
250__libcpp_db::__erase_i(void* __i)
251{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000252#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000253 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000254#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000255 if (__ibeg_ != __iend_)
256 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000257 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000258 __i_node* p = __ibeg_[hi];
259 if (p != nullptr)
260 {
261 __i_node* q = nullptr;
262 while (p->__i_ != __i)
263 {
264 q = p;
265 p = p->__next_;
266 if (p == nullptr)
267 return;
268 }
269 if (q == nullptr)
270 __ibeg_[hi] = p->__next_;
271 else
272 q->__next_ = p->__next_;
273 __c_node* c = p->__c_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000274 --__isz_;
275 if (c != nullptr)
276 c->__remove(p);
Eric Fiselier799b25d2015-03-19 03:20:02 +0000277 free(p);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000278 }
279 }
280}
281
282void
283__libcpp_db::__invalidate_all(void* __c)
284{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000285#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000286 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000287#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000288 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000289 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000290 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
291 __c_node* p = __cbeg_[hc];
292 if (p == nullptr)
293 return;
294 while (p->__c_ != __c)
295 {
296 p = p->__next_;
297 if (p == nullptr)
298 return;
299 }
300 while (p->end_ != p->beg_)
301 {
302 --p->end_;
303 (*p->end_)->__c_ = nullptr;
304 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000305 }
306}
307
308__c_node*
309__libcpp_db::__find_c_and_lock(void* __c) const
310{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000311#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000312 mut().lock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000313#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000314 if (__cend_ == __cbeg_)
315 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000316#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000317 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000318#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000319 return nullptr;
320 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000321 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000322 __c_node* p = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000323 if (p == nullptr)
324 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000325#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000326 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000327#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000328 return nullptr;
329 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000330 while (p->__c_ != __c)
331 {
332 p = p->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000333 if (p == nullptr)
334 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000335#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000336 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000337#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000338 return nullptr;
339 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000340 }
341 return p;
342}
343
Howard Hinnantb399c602011-09-27 23:55:03 +0000344__c_node*
345__libcpp_db::__find_c(void* __c) const
346{
Howard Hinnant28b24882011-12-01 20:21:04 +0000347 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000348 __c_node* p = __cbeg_[hc];
349 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
350 while (p->__c_ != __c)
351 {
352 p = p->__next_;
353 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
354 }
355 return p;
356}
357
Howard Hinnant27e0e772011-09-14 18:33:51 +0000358void
359__libcpp_db::unlock() const
360{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000361#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000362 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000363#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000364}
365
366void
367__libcpp_db::__erase_c(void* __c)
368{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000369#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000370 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000371#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000372 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000373 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000374 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
375 __c_node* p = __cbeg_[hc];
376 if (p == nullptr)
377 return;
378 __c_node* q = nullptr;
379 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
380 while (p->__c_ != __c)
381 {
382 q = p;
383 p = p->__next_;
384 if (p == nullptr)
385 return;
386 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
387 }
388 if (q == nullptr)
389 __cbeg_[hc] = p->__next_;
390 else
391 q->__next_ = p->__next_;
392 while (p->end_ != p->beg_)
393 {
394 --p->end_;
395 (*p->end_)->__c_ = nullptr;
396 }
397 free(p->beg_);
398 free(p);
399 --__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000400 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000401}
402
403void
404__libcpp_db::__iterator_copy(void* __i, const void* __i0)
405{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000406#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000407 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000408#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000409 __i_node* i = __find_iterator(__i);
410 __i_node* i0 = __find_iterator(__i0);
411 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
Howard Hinnant17e485c2013-04-05 17:58:52 +0000412 if (i == nullptr && i0 != nullptr)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000413 i = __insert_iterator(__i);
414 __c_node* c = i != nullptr ? i->__c_ : nullptr;
415 if (c != c0)
416 {
417 if (c != nullptr)
418 c->__remove(i);
419 if (i != nullptr)
420 {
421 i->__c_ = nullptr;
422 if (c0 != nullptr)
423 {
424 i->__c_ = c0;
425 i->__c_->__add(i);
426 }
427 }
428 }
429}
430
431bool
432__libcpp_db::__dereferenceable(const void* __i) const
433{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000434#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000435 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000436#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000437 __i_node* i = __find_iterator(__i);
438 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
439}
440
441bool
442__libcpp_db::__decrementable(const void* __i) const
443{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000444#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000445 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000446#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000447 __i_node* i = __find_iterator(__i);
448 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
449}
450
451bool
452__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
453{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000454#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000455 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000456#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000457 __i_node* i = __find_iterator(__i);
458 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
459}
460
461bool
462__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
463{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000464#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000465 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000466#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000467 __i_node* i = __find_iterator(__i);
468 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
469}
470
471bool
Howard Hinnante6ff0b62013-08-02 00:26:35 +0000472__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
Howard Hinnant27e0e772011-09-14 18:33:51 +0000473{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000474#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000475 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000476#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000477 __i_node* i = __find_iterator(__i);
478 __i_node* j = __find_iterator(__j);
479 __c_node* ci = i != nullptr ? i->__c_ : nullptr;
480 __c_node* cj = j != nullptr ? j->__c_ : nullptr;
481 return ci != nullptr && ci == cj;
482}
483
484void
485__libcpp_db::swap(void* c1, void* c2)
486{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000487#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000488 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000489#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000490 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000491 __c_node* p1 = __cbeg_[hc];
492 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
493 while (p1->__c_ != c1)
494 {
495 p1 = p1->__next_;
496 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
497 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000498 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000499 __c_node* p2 = __cbeg_[hc];
500 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
501 while (p2->__c_ != c2)
502 {
503 p2 = p2->__next_;
504 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
505 }
506 std::swap(p1->beg_, p2->beg_);
507 std::swap(p1->end_, p2->end_);
508 std::swap(p1->cap_, p2->cap_);
509 for (__i_node** p = p1->beg_; p != p1->end_; ++p)
510 (*p)->__c_ = p1;
511 for (__i_node** p = p2->beg_; p != p2->end_; ++p)
512 (*p)->__c_ = p2;
513}
514
Howard Hinnantc90aa632011-09-16 19:52:23 +0000515void
516__libcpp_db::__insert_i(void* __i)
517{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000518#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantc90aa632011-09-16 19:52:23 +0000519 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000520#endif
Howard Hinnantc90aa632011-09-16 19:52:23 +0000521 __insert_iterator(__i);
522}
523
Howard Hinnantb399c602011-09-27 23:55:03 +0000524void
525__c_node::__add(__i_node* i)
526{
527 if (end_ == cap_)
528 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000529 size_t nc = 2*static_cast<size_t>(cap_ - beg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000530 if (nc == 0)
531 nc = 1;
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000532 __i_node** beg =
533 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
Howard Hinnantb399c602011-09-27 23:55:03 +0000534 if (beg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000535 __throw_bad_alloc();
536
Howard Hinnantb399c602011-09-27 23:55:03 +0000537 if (nc > 1)
538 memcpy(beg, beg_, nc/2*sizeof(__i_node*));
539 free(beg_);
540 beg_ = beg;
541 end_ = beg_ + nc/2;
542 cap_ = beg_ + nc;
543 }
544 *end_++ = i;
545}
546
Howard Hinnant27e0e772011-09-14 18:33:51 +0000547// private api
548
549_LIBCPP_HIDDEN
550__i_node*
551__libcpp_db::__insert_iterator(void* __i)
552{
Howard Hinnant28b24882011-12-01 20:21:04 +0000553 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000554 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000555 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000556 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000557 if (ibeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000558 __throw_bad_alloc();
559
Howard Hinnant27e0e772011-09-14 18:33:51 +0000560 for (__i_node** p = __ibeg_; p != __iend_; ++p)
561 {
562 __i_node* q = *p;
563 while (q != nullptr)
564 {
565 size_t h = hash<void*>()(q->__i_) % nc;
566 __i_node* r = q->__next_;
567 q->__next_ = ibeg[h];
568 ibeg[h] = q;
569 q = r;
570 }
571 }
572 free(__ibeg_);
573 __ibeg_ = ibeg;
574 __iend_ = __ibeg_ + nc;
575 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000576 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000577 __i_node* p = __ibeg_[hi];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000578 __i_node* r = __ibeg_[hi] =
579 static_cast<__i_node*>(malloc(sizeof(__i_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000580 if (r == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000581 __throw_bad_alloc();
582
Howard Hinnant27e0e772011-09-14 18:33:51 +0000583 ::new(r) __i_node(__i, p, nullptr);
584 ++__isz_;
585 return r;
586}
587
588_LIBCPP_HIDDEN
589__i_node*
590__libcpp_db::__find_iterator(const void* __i) const
591{
592 __i_node* r = nullptr;
593 if (__ibeg_ != __iend_)
594 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000595 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000596 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
597 {
598 if (nd->__i_ == __i)
599 {
600 r = nd;
601 break;
602 }
603 }
604 }
605 return r;
606}
607
608_LIBCPP_HIDDEN
609void
Howard Hinnant27e0e772011-09-14 18:33:51 +0000610__c_node::__remove(__i_node* p)
611{
612 __i_node** r = find(beg_, end_, p);
613 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
614 if (--end_ != r)
Howard Hinnant28b24882011-12-01 20:21:04 +0000615 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000616}
617
618_LIBCPP_END_NAMESPACE_STD