blob: 0f75d8ce9b623684935ab85acb66be41add57e31 [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 Fiselier873b8d32019-03-18 21:50:12 +000020std::string __libcpp_debug_info::what() const {
21 string msg = __file_;
22 msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '";
23 msg += __pred_;
Eric Fiselierfb825432016-12-28 04:58:52 +000024 msg += "' failed. ";
Eric Fiselier873b8d32019-03-18 21:50:12 +000025 msg += __msg_;
Eric Fiselierfb825432016-12-28 04:58:52 +000026 return msg;
27}
Eric Fiselier873b8d32019-03-18 21:50:12 +000028_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
29 std::fprintf(stderr, "%s\n", info.what().c_str());
30 std::abort();
31}
Eric Fiselierfb825432016-12-28 04:58:52 +000032
33_LIBCPP_SAFE_STATIC __libcpp_debug_function_type
34 __libcpp_debug_function = __libcpp_abort_debug_function;
35
36bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
37 __libcpp_debug_function = __func;
38 return true;
39}
40
Howard Hinnant8331b762013-03-06 23:30:19 +000041_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000042__libcpp_db*
43__get_db()
44{
45 static __libcpp_db db;
46 return &db;
Howard Hinnant434ebf72012-12-27 18:46:00 +000047}
Howard Hinnant27e0e772011-09-14 18:33:51 +000048
Howard Hinnant8331b762013-03-06 23:30:19 +000049_LIBCPP_FUNC_VIS
Howard Hinnant27e0e772011-09-14 18:33:51 +000050const __libcpp_db*
51__get_const_db()
52{
53 return __get_db();
54}
55
56namespace
57{
58
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000059#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +000060typedef mutex mutex_type;
Howard Hinnant27e0e772011-09-14 18:33:51 +000061typedef lock_guard<mutex_type> WLock;
62typedef lock_guard<mutex_type> RLock;
63
64mutex_type&
65mut()
66{
67 static mutex_type m;
68 return m;
69}
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000070#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +000071
72} // unnamed namespace
73
74__i_node::~__i_node()
75{
76 if (__next_)
77 {
78 __next_->~__i_node();
79 free(__next_);
80 }
81}
82
83__c_node::~__c_node()
84{
85 free(beg_);
86 if (__next_)
87 {
88 __next_->~__c_node();
89 free(__next_);
90 }
91}
92
93__libcpp_db::__libcpp_db()
94 : __cbeg_(nullptr),
95 __cend_(nullptr),
96 __csz_(0),
97 __ibeg_(nullptr),
98 __iend_(nullptr),
99 __isz_(0)
100{
101}
102
103__libcpp_db::~__libcpp_db()
104{
105 if (__cbeg_)
106 {
107 for (__c_node** p = __cbeg_; p != __cend_; ++p)
108 {
109 if (*p != nullptr)
110 {
111 (*p)->~__c_node();
112 free(*p);
113 }
114 }
115 free(__cbeg_);
116 }
117 if (__ibeg_)
118 {
119 for (__i_node** p = __ibeg_; p != __iend_; ++p)
120 {
121 if (*p != nullptr)
122 {
123 (*p)->~__i_node();
124 free(*p);
125 }
126 }
127 free(__ibeg_);
128 }
129}
130
131void*
132__libcpp_db::__find_c_from_i(void* __i) const
133{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000134#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000135 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000136#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000137 __i_node* i = __find_iterator(__i);
Howard Hinnant17e485c2013-04-05 17:58:52 +0000138 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
Howard Hinnantc90aa632011-09-16 19:52:23 +0000139 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000140}
141
142void
143__libcpp_db::__insert_ic(void* __i, const void* __c)
144{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000145#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000146 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000147#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000148 if (__cbeg_ == __cend_)
149 return;
Howard Hinnant28b24882011-12-01 20:21:04 +0000150 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000151 __c_node* c = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000152 if (c == nullptr)
153 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000154 while (c->__c_ != __c)
155 {
156 c = c->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000157 if (c == nullptr)
158 return;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000159 }
Howard Hinnant8ea98242013-08-23 17:37:05 +0000160 __i_node* i = __insert_iterator(__i);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000161 c->__add(i);
162 i->__c_ = c;
163}
164
Eric Fiselieraed4eab2019-03-05 02:10:31 +0000165void
166__libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000167{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000168#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000169 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000170#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000171 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000172 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000173 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000174 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000175 if (cbeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000176 __throw_bad_alloc();
177
Howard Hinnant27e0e772011-09-14 18:33:51 +0000178 for (__c_node** p = __cbeg_; p != __cend_; ++p)
179 {
180 __c_node* q = *p;
181 while (q != nullptr)
182 {
183 size_t h = hash<void*>()(q->__c_) % nc;
184 __c_node* r = q->__next_;
185 q->__next_ = cbeg[h];
186 cbeg[h] = q;
187 q = r;
188 }
189 }
190 free(__cbeg_);
191 __cbeg_ = cbeg;
192 __cend_ = __cbeg_ + nc;
193 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000194 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000195 __c_node* p = __cbeg_[hc];
Eric Fiselieraed4eab2019-03-05 02:10:31 +0000196 void *buf = malloc(sizeof(__c_node));
197 if (buf == nullptr)
198 __throw_bad_alloc();
199 __cbeg_[hc] = __fn(buf, __c, p);
Marshall Clow8fea1612016-08-25 15:09:01 +0000200
Howard Hinnant27e0e772011-09-14 18:33:51 +0000201 ++__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000202}
203
204void
205__libcpp_db::__erase_i(void* __i)
206{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000207#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000208 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000209#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000210 if (__ibeg_ != __iend_)
211 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000212 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000213 __i_node* p = __ibeg_[hi];
214 if (p != nullptr)
215 {
216 __i_node* q = nullptr;
217 while (p->__i_ != __i)
218 {
219 q = p;
220 p = p->__next_;
221 if (p == nullptr)
222 return;
223 }
224 if (q == nullptr)
225 __ibeg_[hi] = p->__next_;
226 else
227 q->__next_ = p->__next_;
228 __c_node* c = p->__c_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000229 --__isz_;
230 if (c != nullptr)
231 c->__remove(p);
Eric Fiselier799b25d2015-03-19 03:20:02 +0000232 free(p);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000233 }
234 }
235}
236
237void
238__libcpp_db::__invalidate_all(void* __c)
239{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000240#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000241 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000242#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000243 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000244 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000245 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
246 __c_node* p = __cbeg_[hc];
247 if (p == nullptr)
248 return;
249 while (p->__c_ != __c)
250 {
251 p = p->__next_;
252 if (p == nullptr)
253 return;
254 }
255 while (p->end_ != p->beg_)
256 {
257 --p->end_;
258 (*p->end_)->__c_ = nullptr;
259 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000260 }
261}
262
263__c_node*
264__libcpp_db::__find_c_and_lock(void* __c) const
265{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000266#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000267 mut().lock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000268#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000269 if (__cend_ == __cbeg_)
270 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000271#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000272 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000273#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000274 return nullptr;
275 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000276 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000277 __c_node* p = __cbeg_[hc];
Howard Hinnant8ea98242013-08-23 17:37:05 +0000278 if (p == nullptr)
279 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000280#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000281 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000282#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000283 return nullptr;
284 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000285 while (p->__c_ != __c)
286 {
287 p = p->__next_;
Howard Hinnant8ea98242013-08-23 17:37:05 +0000288 if (p == nullptr)
289 {
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000290#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant8ea98242013-08-23 17:37:05 +0000291 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000292#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000293 return nullptr;
294 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000295 }
296 return p;
297}
298
Howard Hinnantb399c602011-09-27 23:55:03 +0000299__c_node*
300__libcpp_db::__find_c(void* __c) const
301{
Howard Hinnant28b24882011-12-01 20:21:04 +0000302 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000303 __c_node* p = __cbeg_[hc];
304 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
305 while (p->__c_ != __c)
306 {
307 p = p->__next_;
308 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
309 }
310 return p;
311}
312
Howard Hinnant27e0e772011-09-14 18:33:51 +0000313void
314__libcpp_db::unlock() const
315{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000316#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000317 mut().unlock();
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000318#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000319}
320
321void
322__libcpp_db::__erase_c(void* __c)
323{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000324#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000325 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000326#endif
Howard Hinnant8ea98242013-08-23 17:37:05 +0000327 if (__cend_ != __cbeg_)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000328 {
Howard Hinnant8ea98242013-08-23 17:37:05 +0000329 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
330 __c_node* p = __cbeg_[hc];
331 if (p == nullptr)
332 return;
333 __c_node* q = nullptr;
334 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
335 while (p->__c_ != __c)
336 {
337 q = p;
338 p = p->__next_;
339 if (p == nullptr)
340 return;
341 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
342 }
343 if (q == nullptr)
344 __cbeg_[hc] = p->__next_;
345 else
346 q->__next_ = p->__next_;
347 while (p->end_ != p->beg_)
348 {
349 --p->end_;
350 (*p->end_)->__c_ = nullptr;
351 }
352 free(p->beg_);
353 free(p);
354 --__csz_;
Howard Hinnant27e0e772011-09-14 18:33:51 +0000355 }
Howard Hinnant27e0e772011-09-14 18:33:51 +0000356}
357
358void
359__libcpp_db::__iterator_copy(void* __i, const void* __i0)
360{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000361#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000362 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000363#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000364 __i_node* i = __find_iterator(__i);
365 __i_node* i0 = __find_iterator(__i0);
366 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
Howard Hinnant17e485c2013-04-05 17:58:52 +0000367 if (i == nullptr && i0 != nullptr)
Howard Hinnant27e0e772011-09-14 18:33:51 +0000368 i = __insert_iterator(__i);
369 __c_node* c = i != nullptr ? i->__c_ : nullptr;
370 if (c != c0)
371 {
372 if (c != nullptr)
373 c->__remove(i);
374 if (i != nullptr)
375 {
376 i->__c_ = nullptr;
377 if (c0 != nullptr)
378 {
379 i->__c_ = c0;
380 i->__c_->__add(i);
381 }
382 }
383 }
384}
385
386bool
387__libcpp_db::__dereferenceable(const void* __i) const
388{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000389#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000390 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000391#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000392 __i_node* i = __find_iterator(__i);
393 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
394}
395
396bool
397__libcpp_db::__decrementable(const void* __i) const
398{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000399#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000400 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000401#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000402 __i_node* i = __find_iterator(__i);
403 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
404}
405
406bool
407__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
408{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000409#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000410 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000411#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000412 __i_node* i = __find_iterator(__i);
413 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
414}
415
416bool
417__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
418{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000419#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000420 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000421#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000422 __i_node* i = __find_iterator(__i);
423 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
424}
425
426bool
Howard Hinnante6ff0b62013-08-02 00:26:35 +0000427__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
Howard Hinnant27e0e772011-09-14 18:33:51 +0000428{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000429#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000430 RLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000431#endif
Howard Hinnant27e0e772011-09-14 18:33:51 +0000432 __i_node* i = __find_iterator(__i);
433 __i_node* j = __find_iterator(__j);
434 __c_node* ci = i != nullptr ? i->__c_ : nullptr;
435 __c_node* cj = j != nullptr ? j->__c_ : nullptr;
436 return ci != nullptr && ci == cj;
437}
438
439void
440__libcpp_db::swap(void* c1, void* c2)
441{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000442#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant27e0e772011-09-14 18:33:51 +0000443 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000444#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000445 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000446 __c_node* p1 = __cbeg_[hc];
447 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
448 while (p1->__c_ != c1)
449 {
450 p1 = p1->__next_;
451 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
452 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000453 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000454 __c_node* p2 = __cbeg_[hc];
455 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
456 while (p2->__c_ != c2)
457 {
458 p2 = p2->__next_;
459 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
460 }
461 std::swap(p1->beg_, p2->beg_);
462 std::swap(p1->end_, p2->end_);
463 std::swap(p1->cap_, p2->cap_);
464 for (__i_node** p = p1->beg_; p != p1->end_; ++p)
465 (*p)->__c_ = p1;
466 for (__i_node** p = p2->beg_; p != p2->end_; ++p)
467 (*p)->__c_ = p2;
468}
469
Howard Hinnantc90aa632011-09-16 19:52:23 +0000470void
471__libcpp_db::__insert_i(void* __i)
472{
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000473#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantc90aa632011-09-16 19:52:23 +0000474 WLock _(mut());
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000475#endif
Howard Hinnantc90aa632011-09-16 19:52:23 +0000476 __insert_iterator(__i);
477}
478
Howard Hinnantb399c602011-09-27 23:55:03 +0000479void
480__c_node::__add(__i_node* i)
481{
482 if (end_ == cap_)
483 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000484 size_t nc = 2*static_cast<size_t>(cap_ - beg_);
Howard Hinnantb399c602011-09-27 23:55:03 +0000485 if (nc == 0)
486 nc = 1;
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000487 __i_node** beg =
488 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
Howard Hinnantb399c602011-09-27 23:55:03 +0000489 if (beg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000490 __throw_bad_alloc();
491
Howard Hinnantb399c602011-09-27 23:55:03 +0000492 if (nc > 1)
493 memcpy(beg, beg_, nc/2*sizeof(__i_node*));
494 free(beg_);
495 beg_ = beg;
496 end_ = beg_ + nc/2;
497 cap_ = beg_ + nc;
498 }
499 *end_++ = i;
500}
501
Howard Hinnant27e0e772011-09-14 18:33:51 +0000502// private api
503
504_LIBCPP_HIDDEN
505__i_node*
506__libcpp_db::__insert_iterator(void* __i)
507{
Howard Hinnant28b24882011-12-01 20:21:04 +0000508 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
Howard Hinnant27e0e772011-09-14 18:33:51 +0000509 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000510 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000511 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000512 if (ibeg == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000513 __throw_bad_alloc();
514
Howard Hinnant27e0e772011-09-14 18:33:51 +0000515 for (__i_node** p = __ibeg_; p != __iend_; ++p)
516 {
517 __i_node* q = *p;
518 while (q != nullptr)
519 {
520 size_t h = hash<void*>()(q->__i_) % nc;
521 __i_node* r = q->__next_;
522 q->__next_ = ibeg[h];
523 ibeg[h] = q;
524 q = r;
525 }
526 }
527 free(__ibeg_);
528 __ibeg_ = ibeg;
529 __iend_ = __ibeg_ + nc;
530 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000531 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000532 __i_node* p = __ibeg_[hi];
Joerg Sonnenberger0962ed52013-04-27 19:13:31 +0000533 __i_node* r = __ibeg_[hi] =
534 static_cast<__i_node*>(malloc(sizeof(__i_node)));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000535 if (r == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +0000536 __throw_bad_alloc();
537
Howard Hinnant27e0e772011-09-14 18:33:51 +0000538 ::new(r) __i_node(__i, p, nullptr);
539 ++__isz_;
540 return r;
541}
542
543_LIBCPP_HIDDEN
544__i_node*
545__libcpp_db::__find_iterator(const void* __i) const
546{
547 __i_node* r = nullptr;
548 if (__ibeg_ != __iend_)
549 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000550 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant27e0e772011-09-14 18:33:51 +0000551 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
552 {
553 if (nd->__i_ == __i)
554 {
555 r = nd;
556 break;
557 }
558 }
559 }
560 return r;
561}
562
563_LIBCPP_HIDDEN
564void
Howard Hinnant27e0e772011-09-14 18:33:51 +0000565__c_node::__remove(__i_node* p)
566{
567 __i_node** r = find(beg_, end_, p);
568 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
569 if (--end_ != r)
Howard Hinnant28b24882011-12-01 20:21:04 +0000570 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
Howard Hinnant27e0e772011-09-14 18:33:51 +0000571}
572
573_LIBCPP_END_NAMESPACE_STD