17a984708SDavid Chisnall //===-------------------------- debug.cpp ---------------------------------===//
27a984708SDavid Chisnall //
37a984708SDavid Chisnall // The LLVM Compiler Infrastructure
47a984708SDavid Chisnall //
57a984708SDavid Chisnall // This file is dual licensed under the MIT and the University of Illinois Open
67a984708SDavid Chisnall // Source Licenses. See LICENSE.TXT for details.
77a984708SDavid Chisnall //
87a984708SDavid Chisnall //===----------------------------------------------------------------------===//
97a984708SDavid Chisnall
107a984708SDavid Chisnall #include "__config"
117a984708SDavid Chisnall #include "__debug"
127a984708SDavid Chisnall #include "functional"
137a984708SDavid Chisnall #include "algorithm"
14*aed8d94eSDimitry Andric #include "string"
15*aed8d94eSDimitry Andric #include "cstdio"
167a984708SDavid Chisnall #include "__hash_table"
177a984708SDavid Chisnall #include "mutex"
187a984708SDavid Chisnall
197a984708SDavid Chisnall _LIBCPP_BEGIN_NAMESPACE_STD
207a984708SDavid Chisnall
make_what_str(__libcpp_debug_info const & info)21*aed8d94eSDimitry Andric static std::string make_what_str(__libcpp_debug_info const& info) {
22*aed8d94eSDimitry Andric string msg = info.__file_;
23*aed8d94eSDimitry Andric msg += ":" + to_string(info.__line_) + ": _LIBCPP_ASSERT '";
24*aed8d94eSDimitry Andric msg += info.__pred_;
25*aed8d94eSDimitry Andric msg += "' failed. ";
26*aed8d94eSDimitry Andric msg += info.__msg_;
27*aed8d94eSDimitry Andric return msg;
28*aed8d94eSDimitry Andric }
29*aed8d94eSDimitry Andric
30*aed8d94eSDimitry Andric _LIBCPP_SAFE_STATIC __libcpp_debug_function_type
31*aed8d94eSDimitry Andric __libcpp_debug_function = __libcpp_abort_debug_function;
32*aed8d94eSDimitry Andric
__libcpp_set_debug_function(__libcpp_debug_function_type __func)33*aed8d94eSDimitry Andric bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
34*aed8d94eSDimitry Andric __libcpp_debug_function = __func;
35*aed8d94eSDimitry Andric return true;
36*aed8d94eSDimitry Andric }
37*aed8d94eSDimitry Andric
__libcpp_abort_debug_function(__libcpp_debug_info const & info)38*aed8d94eSDimitry Andric _LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
39*aed8d94eSDimitry Andric std::fprintf(stderr, "%s\n", make_what_str(info).c_str());
40*aed8d94eSDimitry Andric std::abort();
41*aed8d94eSDimitry Andric }
42*aed8d94eSDimitry Andric
__libcpp_throw_debug_function(__libcpp_debug_info const & info)43*aed8d94eSDimitry Andric _LIBCPP_NORETURN void __libcpp_throw_debug_function(__libcpp_debug_info const& info) {
44*aed8d94eSDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
45*aed8d94eSDimitry Andric throw __libcpp_debug_exception(info);
46*aed8d94eSDimitry Andric #else
47*aed8d94eSDimitry Andric __libcpp_abort_debug_function(info);
48*aed8d94eSDimitry Andric #endif
49*aed8d94eSDimitry Andric }
50*aed8d94eSDimitry Andric
51*aed8d94eSDimitry Andric struct __libcpp_debug_exception::__libcpp_debug_exception_imp {
52*aed8d94eSDimitry Andric __libcpp_debug_info __info_;
53*aed8d94eSDimitry Andric std::string __what_str_;
54*aed8d94eSDimitry Andric };
55*aed8d94eSDimitry Andric
__libcpp_debug_exception()56*aed8d94eSDimitry Andric __libcpp_debug_exception::__libcpp_debug_exception() _NOEXCEPT
57*aed8d94eSDimitry Andric : __imp_(nullptr) {
58*aed8d94eSDimitry Andric }
59*aed8d94eSDimitry Andric
__libcpp_debug_exception(__libcpp_debug_info const & info)60*aed8d94eSDimitry Andric __libcpp_debug_exception::__libcpp_debug_exception(
61*aed8d94eSDimitry Andric __libcpp_debug_info const& info) : __imp_(new __libcpp_debug_exception_imp)
62*aed8d94eSDimitry Andric {
63*aed8d94eSDimitry Andric __imp_->__info_ = info;
64*aed8d94eSDimitry Andric __imp_->__what_str_ = make_what_str(info);
65*aed8d94eSDimitry Andric }
__libcpp_debug_exception(__libcpp_debug_exception const & other)66*aed8d94eSDimitry Andric __libcpp_debug_exception::__libcpp_debug_exception(
67*aed8d94eSDimitry Andric __libcpp_debug_exception const& other) : __imp_(nullptr) {
68*aed8d94eSDimitry Andric if (other.__imp_)
69*aed8d94eSDimitry Andric __imp_ = new __libcpp_debug_exception_imp(*other.__imp_);
70*aed8d94eSDimitry Andric }
71*aed8d94eSDimitry Andric
~__libcpp_debug_exception()72*aed8d94eSDimitry Andric __libcpp_debug_exception::~__libcpp_debug_exception() _NOEXCEPT {
73*aed8d94eSDimitry Andric if (__imp_)
74*aed8d94eSDimitry Andric delete __imp_;
75*aed8d94eSDimitry Andric }
76*aed8d94eSDimitry Andric
what() const77*aed8d94eSDimitry Andric const char* __libcpp_debug_exception::what() const _NOEXCEPT {
78*aed8d94eSDimitry Andric if (__imp_)
79*aed8d94eSDimitry Andric return __imp_->__what_str_.c_str();
80*aed8d94eSDimitry Andric return "__libcpp_debug_exception";
81*aed8d94eSDimitry Andric }
82*aed8d94eSDimitry Andric
831bf9f7c1SDimitry Andric _LIBCPP_FUNC_VIS
847a984708SDavid Chisnall __libcpp_db*
__get_db()857a984708SDavid Chisnall __get_db()
867a984708SDavid Chisnall {
877a984708SDavid Chisnall static __libcpp_db db;
887a984708SDavid Chisnall return &db;
89cfdf2879SDavid Chisnall }
907a984708SDavid Chisnall
911bf9f7c1SDimitry Andric _LIBCPP_FUNC_VIS
927a984708SDavid Chisnall const __libcpp_db*
__get_const_db()937a984708SDavid Chisnall __get_const_db()
947a984708SDavid Chisnall {
957a984708SDavid Chisnall return __get_db();
967a984708SDavid Chisnall }
977a984708SDavid Chisnall
987a984708SDavid Chisnall namespace
997a984708SDavid Chisnall {
1007a984708SDavid Chisnall
101d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1027a984708SDavid Chisnall typedef mutex mutex_type;
1037a984708SDavid Chisnall typedef lock_guard<mutex_type> WLock;
1047a984708SDavid Chisnall typedef lock_guard<mutex_type> RLock;
1057a984708SDavid Chisnall
1067a984708SDavid Chisnall mutex_type&
mut()1077a984708SDavid Chisnall mut()
1087a984708SDavid Chisnall {
1097a984708SDavid Chisnall static mutex_type m;
1107a984708SDavid Chisnall return m;
1117a984708SDavid Chisnall }
112d72607e9SDimitry Andric #endif // !_LIBCPP_HAS_NO_THREADS
1137a984708SDavid Chisnall
1147a984708SDavid Chisnall } // unnamed namespace
1157a984708SDavid Chisnall
~__i_node()1167a984708SDavid Chisnall __i_node::~__i_node()
1177a984708SDavid Chisnall {
1187a984708SDavid Chisnall if (__next_)
1197a984708SDavid Chisnall {
1207a984708SDavid Chisnall __next_->~__i_node();
1217a984708SDavid Chisnall free(__next_);
1227a984708SDavid Chisnall }
1237a984708SDavid Chisnall }
1247a984708SDavid Chisnall
~__c_node()1257a984708SDavid Chisnall __c_node::~__c_node()
1267a984708SDavid Chisnall {
1277a984708SDavid Chisnall free(beg_);
1287a984708SDavid Chisnall if (__next_)
1297a984708SDavid Chisnall {
1307a984708SDavid Chisnall __next_->~__c_node();
1317a984708SDavid Chisnall free(__next_);
1327a984708SDavid Chisnall }
1337a984708SDavid Chisnall }
1347a984708SDavid Chisnall
__libcpp_db()1357a984708SDavid Chisnall __libcpp_db::__libcpp_db()
1367a984708SDavid Chisnall : __cbeg_(nullptr),
1377a984708SDavid Chisnall __cend_(nullptr),
1387a984708SDavid Chisnall __csz_(0),
1397a984708SDavid Chisnall __ibeg_(nullptr),
1407a984708SDavid Chisnall __iend_(nullptr),
1417a984708SDavid Chisnall __isz_(0)
1427a984708SDavid Chisnall {
1437a984708SDavid Chisnall }
1447a984708SDavid Chisnall
~__libcpp_db()1457a984708SDavid Chisnall __libcpp_db::~__libcpp_db()
1467a984708SDavid Chisnall {
1477a984708SDavid Chisnall if (__cbeg_)
1487a984708SDavid Chisnall {
1497a984708SDavid Chisnall for (__c_node** p = __cbeg_; p != __cend_; ++p)
1507a984708SDavid Chisnall {
1517a984708SDavid Chisnall if (*p != nullptr)
1527a984708SDavid Chisnall {
1537a984708SDavid Chisnall (*p)->~__c_node();
1547a984708SDavid Chisnall free(*p);
1557a984708SDavid Chisnall }
1567a984708SDavid Chisnall }
1577a984708SDavid Chisnall free(__cbeg_);
1587a984708SDavid Chisnall }
1597a984708SDavid Chisnall if (__ibeg_)
1607a984708SDavid Chisnall {
1617a984708SDavid Chisnall for (__i_node** p = __ibeg_; p != __iend_; ++p)
1627a984708SDavid Chisnall {
1637a984708SDavid Chisnall if (*p != nullptr)
1647a984708SDavid Chisnall {
1657a984708SDavid Chisnall (*p)->~__i_node();
1667a984708SDavid Chisnall free(*p);
1677a984708SDavid Chisnall }
1687a984708SDavid Chisnall }
1697a984708SDavid Chisnall free(__ibeg_);
1707a984708SDavid Chisnall }
1717a984708SDavid Chisnall }
1727a984708SDavid Chisnall
1737a984708SDavid Chisnall void*
__find_c_from_i(void * __i) const1747a984708SDavid Chisnall __libcpp_db::__find_c_from_i(void* __i) const
1757a984708SDavid Chisnall {
176d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1777a984708SDavid Chisnall RLock _(mut());
178d72607e9SDimitry Andric #endif
1797a984708SDavid Chisnall __i_node* i = __find_iterator(__i);
1801bf9f7c1SDimitry Andric _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
1817a984708SDavid Chisnall return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
1827a984708SDavid Chisnall }
1837a984708SDavid Chisnall
1847a984708SDavid Chisnall void
__insert_ic(void * __i,const void * __c)1857a984708SDavid Chisnall __libcpp_db::__insert_ic(void* __i, const void* __c)
1867a984708SDavid Chisnall {
187d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1887a984708SDavid Chisnall WLock _(mut());
189d72607e9SDimitry Andric #endif
1904f7ab58eSDimitry Andric if (__cbeg_ == __cend_)
1914f7ab58eSDimitry Andric return;
19294e3ee44SDavid Chisnall size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
1937a984708SDavid Chisnall __c_node* c = __cbeg_[hc];
1944f7ab58eSDimitry Andric if (c == nullptr)
1954f7ab58eSDimitry Andric return;
1967a984708SDavid Chisnall while (c->__c_ != __c)
1977a984708SDavid Chisnall {
1987a984708SDavid Chisnall c = c->__next_;
1994f7ab58eSDimitry Andric if (c == nullptr)
2004f7ab58eSDimitry Andric return;
2017a984708SDavid Chisnall }
2024f7ab58eSDimitry Andric __i_node* i = __insert_iterator(__i);
2037a984708SDavid Chisnall c->__add(i);
2047a984708SDavid Chisnall i->__c_ = c;
2057a984708SDavid Chisnall }
2067a984708SDavid Chisnall
2077a984708SDavid Chisnall __c_node*
__insert_c(void * __c)2087a984708SDavid Chisnall __libcpp_db::__insert_c(void* __c)
2097a984708SDavid Chisnall {
210d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2117a984708SDavid Chisnall WLock _(mut());
212d72607e9SDimitry Andric #endif
21394e3ee44SDavid Chisnall if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
2147a984708SDavid Chisnall {
21594e3ee44SDavid Chisnall size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
2164bab9fd9SDavid Chisnall __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
2177a984708SDavid Chisnall if (cbeg == nullptr)
218*aed8d94eSDimitry Andric __throw_bad_alloc();
219*aed8d94eSDimitry Andric
2207a984708SDavid Chisnall for (__c_node** p = __cbeg_; p != __cend_; ++p)
2217a984708SDavid Chisnall {
2227a984708SDavid Chisnall __c_node* q = *p;
2237a984708SDavid Chisnall while (q != nullptr)
2247a984708SDavid Chisnall {
2257a984708SDavid Chisnall size_t h = hash<void*>()(q->__c_) % nc;
2267a984708SDavid Chisnall __c_node* r = q->__next_;
2277a984708SDavid Chisnall q->__next_ = cbeg[h];
2287a984708SDavid Chisnall cbeg[h] = q;
2297a984708SDavid Chisnall q = r;
2307a984708SDavid Chisnall }
2317a984708SDavid Chisnall }
2327a984708SDavid Chisnall free(__cbeg_);
2337a984708SDavid Chisnall __cbeg_ = cbeg;
2347a984708SDavid Chisnall __cend_ = __cbeg_ + nc;
2357a984708SDavid Chisnall }
23694e3ee44SDavid Chisnall size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2377a984708SDavid Chisnall __c_node* p = __cbeg_[hc];
2384bab9fd9SDavid Chisnall __c_node* r = __cbeg_[hc] =
2394bab9fd9SDavid Chisnall static_cast<__c_node*>(malloc(sizeof(__c_node)));
2407a984708SDavid Chisnall if (__cbeg_[hc] == nullptr)
241*aed8d94eSDimitry Andric __throw_bad_alloc();
242*aed8d94eSDimitry Andric
2437a984708SDavid Chisnall r->__c_ = __c;
2447a984708SDavid Chisnall r->__next_ = p;
2457a984708SDavid Chisnall ++__csz_;
2467a984708SDavid Chisnall return r;
2477a984708SDavid Chisnall }
2487a984708SDavid Chisnall
2497a984708SDavid Chisnall void
__erase_i(void * __i)2507a984708SDavid Chisnall __libcpp_db::__erase_i(void* __i)
2517a984708SDavid Chisnall {
252d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2537a984708SDavid Chisnall WLock _(mut());
254d72607e9SDimitry Andric #endif
2557a984708SDavid Chisnall if (__ibeg_ != __iend_)
2567a984708SDavid Chisnall {
25794e3ee44SDavid Chisnall size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
2587a984708SDavid Chisnall __i_node* p = __ibeg_[hi];
2597a984708SDavid Chisnall if (p != nullptr)
2607a984708SDavid Chisnall {
2617a984708SDavid Chisnall __i_node* q = nullptr;
2627a984708SDavid Chisnall while (p->__i_ != __i)
2637a984708SDavid Chisnall {
2647a984708SDavid Chisnall q = p;
2657a984708SDavid Chisnall p = p->__next_;
2667a984708SDavid Chisnall if (p == nullptr)
2677a984708SDavid Chisnall return;
2687a984708SDavid Chisnall }
2697a984708SDavid Chisnall if (q == nullptr)
2707a984708SDavid Chisnall __ibeg_[hi] = p->__next_;
2717a984708SDavid Chisnall else
2727a984708SDavid Chisnall q->__next_ = p->__next_;
2737a984708SDavid Chisnall __c_node* c = p->__c_;
2747a984708SDavid Chisnall --__isz_;
2757a984708SDavid Chisnall if (c != nullptr)
2767a984708SDavid Chisnall c->__remove(p);
277854fa44bSDimitry Andric free(p);
2787a984708SDavid Chisnall }
2797a984708SDavid Chisnall }
2807a984708SDavid Chisnall }
2817a984708SDavid Chisnall
2827a984708SDavid Chisnall void
__invalidate_all(void * __c)2837a984708SDavid Chisnall __libcpp_db::__invalidate_all(void* __c)
2847a984708SDavid Chisnall {
285d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2867a984708SDavid Chisnall WLock _(mut());
287d72607e9SDimitry Andric #endif
2884f7ab58eSDimitry Andric if (__cend_ != __cbeg_)
2894f7ab58eSDimitry Andric {
29094e3ee44SDavid Chisnall size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2917a984708SDavid Chisnall __c_node* p = __cbeg_[hc];
2924f7ab58eSDimitry Andric if (p == nullptr)
2934f7ab58eSDimitry Andric return;
2947a984708SDavid Chisnall while (p->__c_ != __c)
2957a984708SDavid Chisnall {
2967a984708SDavid Chisnall p = p->__next_;
2974f7ab58eSDimitry Andric if (p == nullptr)
2984f7ab58eSDimitry Andric return;
2997a984708SDavid Chisnall }
3007a984708SDavid Chisnall while (p->end_ != p->beg_)
3017a984708SDavid Chisnall {
3027a984708SDavid Chisnall --p->end_;
3037a984708SDavid Chisnall (*p->end_)->__c_ = nullptr;
3047a984708SDavid Chisnall }
3057a984708SDavid Chisnall }
3064f7ab58eSDimitry Andric }
3077a984708SDavid Chisnall
3087a984708SDavid Chisnall __c_node*
__find_c_and_lock(void * __c) const3097a984708SDavid Chisnall __libcpp_db::__find_c_and_lock(void* __c) const
3107a984708SDavid Chisnall {
311d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3127a984708SDavid Chisnall mut().lock();
313d72607e9SDimitry Andric #endif
3144f7ab58eSDimitry Andric if (__cend_ == __cbeg_)
3154f7ab58eSDimitry Andric {
316d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3174f7ab58eSDimitry Andric mut().unlock();
318d72607e9SDimitry Andric #endif
3194f7ab58eSDimitry Andric return nullptr;
3204f7ab58eSDimitry Andric }
32194e3ee44SDavid Chisnall size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
3227a984708SDavid Chisnall __c_node* p = __cbeg_[hc];
3234f7ab58eSDimitry Andric if (p == nullptr)
3244f7ab58eSDimitry Andric {
325d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3264f7ab58eSDimitry Andric mut().unlock();
327d72607e9SDimitry Andric #endif
3284f7ab58eSDimitry Andric return nullptr;
3294f7ab58eSDimitry Andric }
3307a984708SDavid Chisnall while (p->__c_ != __c)
3317a984708SDavid Chisnall {
3327a984708SDavid Chisnall p = p->__next_;
3334f7ab58eSDimitry Andric if (p == nullptr)
3344f7ab58eSDimitry Andric {
335d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3364f7ab58eSDimitry Andric mut().unlock();
337d72607e9SDimitry Andric #endif
3384f7ab58eSDimitry Andric return nullptr;
3394f7ab58eSDimitry Andric }
3407a984708SDavid Chisnall }
3417a984708SDavid Chisnall return p;
3427a984708SDavid Chisnall }
3437a984708SDavid Chisnall
3447a984708SDavid Chisnall __c_node*
__find_c(void * __c) const3457a984708SDavid Chisnall __libcpp_db::__find_c(void* __c) const
3467a984708SDavid Chisnall {
34794e3ee44SDavid Chisnall size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
3487a984708SDavid Chisnall __c_node* p = __cbeg_[hc];
3497a984708SDavid Chisnall _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
3507a984708SDavid Chisnall while (p->__c_ != __c)
3517a984708SDavid Chisnall {
3527a984708SDavid Chisnall p = p->__next_;
3537a984708SDavid Chisnall _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
3547a984708SDavid Chisnall }
3557a984708SDavid Chisnall return p;
3567a984708SDavid Chisnall }
3577a984708SDavid Chisnall
3587a984708SDavid Chisnall void
unlock() const3597a984708SDavid Chisnall __libcpp_db::unlock() const
3607a984708SDavid Chisnall {
361d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3627a984708SDavid Chisnall mut().unlock();
363d72607e9SDimitry Andric #endif
3647a984708SDavid Chisnall }
3657a984708SDavid Chisnall
3667a984708SDavid Chisnall void
__erase_c(void * __c)3677a984708SDavid Chisnall __libcpp_db::__erase_c(void* __c)
3687a984708SDavid Chisnall {
369d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3707a984708SDavid Chisnall WLock _(mut());
371d72607e9SDimitry Andric #endif
3724f7ab58eSDimitry Andric if (__cend_ != __cbeg_)
3734f7ab58eSDimitry Andric {
37494e3ee44SDavid Chisnall size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
3757a984708SDavid Chisnall __c_node* p = __cbeg_[hc];
3764f7ab58eSDimitry Andric if (p == nullptr)
3774f7ab58eSDimitry Andric return;
3787a984708SDavid Chisnall __c_node* q = nullptr;
3797a984708SDavid Chisnall _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
3807a984708SDavid Chisnall while (p->__c_ != __c)
3817a984708SDavid Chisnall {
3827a984708SDavid Chisnall q = p;
3837a984708SDavid Chisnall p = p->__next_;
3844f7ab58eSDimitry Andric if (p == nullptr)
3854f7ab58eSDimitry Andric return;
3867a984708SDavid Chisnall _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
3877a984708SDavid Chisnall }
3887a984708SDavid Chisnall if (q == nullptr)
3897a984708SDavid Chisnall __cbeg_[hc] = p->__next_;
3907a984708SDavid Chisnall else
3917a984708SDavid Chisnall q->__next_ = p->__next_;
3927a984708SDavid Chisnall while (p->end_ != p->beg_)
3937a984708SDavid Chisnall {
3947a984708SDavid Chisnall --p->end_;
3957a984708SDavid Chisnall (*p->end_)->__c_ = nullptr;
3967a984708SDavid Chisnall }
3977a984708SDavid Chisnall free(p->beg_);
3987a984708SDavid Chisnall free(p);
3997a984708SDavid Chisnall --__csz_;
4007a984708SDavid Chisnall }
4014f7ab58eSDimitry Andric }
4027a984708SDavid Chisnall
4037a984708SDavid Chisnall void
__iterator_copy(void * __i,const void * __i0)4047a984708SDavid Chisnall __libcpp_db::__iterator_copy(void* __i, const void* __i0)
4057a984708SDavid Chisnall {
406d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4077a984708SDavid Chisnall WLock _(mut());
408d72607e9SDimitry Andric #endif
4097a984708SDavid Chisnall __i_node* i = __find_iterator(__i);
4107a984708SDavid Chisnall __i_node* i0 = __find_iterator(__i0);
4117a984708SDavid Chisnall __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
4121bf9f7c1SDimitry Andric if (i == nullptr && i0 != nullptr)
4137a984708SDavid Chisnall i = __insert_iterator(__i);
4147a984708SDavid Chisnall __c_node* c = i != nullptr ? i->__c_ : nullptr;
4157a984708SDavid Chisnall if (c != c0)
4167a984708SDavid Chisnall {
4177a984708SDavid Chisnall if (c != nullptr)
4187a984708SDavid Chisnall c->__remove(i);
4197a984708SDavid Chisnall if (i != nullptr)
4207a984708SDavid Chisnall {
4217a984708SDavid Chisnall i->__c_ = nullptr;
4227a984708SDavid Chisnall if (c0 != nullptr)
4237a984708SDavid Chisnall {
4247a984708SDavid Chisnall i->__c_ = c0;
4257a984708SDavid Chisnall i->__c_->__add(i);
4267a984708SDavid Chisnall }
4277a984708SDavid Chisnall }
4287a984708SDavid Chisnall }
4297a984708SDavid Chisnall }
4307a984708SDavid Chisnall
4317a984708SDavid Chisnall bool
__dereferenceable(const void * __i) const4327a984708SDavid Chisnall __libcpp_db::__dereferenceable(const void* __i) const
4337a984708SDavid Chisnall {
434d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4357a984708SDavid Chisnall RLock _(mut());
436d72607e9SDimitry Andric #endif
4377a984708SDavid Chisnall __i_node* i = __find_iterator(__i);
4387a984708SDavid Chisnall return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
4397a984708SDavid Chisnall }
4407a984708SDavid Chisnall
4417a984708SDavid Chisnall bool
__decrementable(const void * __i) const4427a984708SDavid Chisnall __libcpp_db::__decrementable(const void* __i) const
4437a984708SDavid Chisnall {
444d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4457a984708SDavid Chisnall RLock _(mut());
446d72607e9SDimitry Andric #endif
4477a984708SDavid Chisnall __i_node* i = __find_iterator(__i);
4487a984708SDavid Chisnall return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
4497a984708SDavid Chisnall }
4507a984708SDavid Chisnall
4517a984708SDavid Chisnall bool
__addable(const void * __i,ptrdiff_t __n) const4527a984708SDavid Chisnall __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
4537a984708SDavid Chisnall {
454d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4557a984708SDavid Chisnall RLock _(mut());
456d72607e9SDimitry Andric #endif
4577a984708SDavid Chisnall __i_node* i = __find_iterator(__i);
4587a984708SDavid Chisnall return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
4597a984708SDavid Chisnall }
4607a984708SDavid Chisnall
4617a984708SDavid Chisnall bool
__subscriptable(const void * __i,ptrdiff_t __n) const4627a984708SDavid Chisnall __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
4637a984708SDavid Chisnall {
464d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4657a984708SDavid Chisnall RLock _(mut());
466d72607e9SDimitry Andric #endif
4677a984708SDavid Chisnall __i_node* i = __find_iterator(__i);
4687a984708SDavid Chisnall return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
4697a984708SDavid Chisnall }
4707a984708SDavid Chisnall
4717a984708SDavid Chisnall bool
__less_than_comparable(const void * __i,const void * __j) const4724f7ab58eSDimitry Andric __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
4737a984708SDavid Chisnall {
474d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4757a984708SDavid Chisnall RLock _(mut());
476d72607e9SDimitry Andric #endif
4777a984708SDavid Chisnall __i_node* i = __find_iterator(__i);
4787a984708SDavid Chisnall __i_node* j = __find_iterator(__j);
4797a984708SDavid Chisnall __c_node* ci = i != nullptr ? i->__c_ : nullptr;
4807a984708SDavid Chisnall __c_node* cj = j != nullptr ? j->__c_ : nullptr;
4817a984708SDavid Chisnall return ci != nullptr && ci == cj;
4827a984708SDavid Chisnall }
4837a984708SDavid Chisnall
4847a984708SDavid Chisnall void
swap(void * c1,void * c2)4857a984708SDavid Chisnall __libcpp_db::swap(void* c1, void* c2)
4867a984708SDavid Chisnall {
487d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4887a984708SDavid Chisnall WLock _(mut());
489d72607e9SDimitry Andric #endif
49094e3ee44SDavid Chisnall size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
4917a984708SDavid Chisnall __c_node* p1 = __cbeg_[hc];
4927a984708SDavid Chisnall _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
4937a984708SDavid Chisnall while (p1->__c_ != c1)
4947a984708SDavid Chisnall {
4957a984708SDavid Chisnall p1 = p1->__next_;
4967a984708SDavid Chisnall _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
4977a984708SDavid Chisnall }
49894e3ee44SDavid Chisnall hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
4997a984708SDavid Chisnall __c_node* p2 = __cbeg_[hc];
5007a984708SDavid Chisnall _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
5017a984708SDavid Chisnall while (p2->__c_ != c2)
5027a984708SDavid Chisnall {
5037a984708SDavid Chisnall p2 = p2->__next_;
5047a984708SDavid Chisnall _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
5057a984708SDavid Chisnall }
5067a984708SDavid Chisnall std::swap(p1->beg_, p2->beg_);
5077a984708SDavid Chisnall std::swap(p1->end_, p2->end_);
5087a984708SDavid Chisnall std::swap(p1->cap_, p2->cap_);
5097a984708SDavid Chisnall for (__i_node** p = p1->beg_; p != p1->end_; ++p)
5107a984708SDavid Chisnall (*p)->__c_ = p1;
5117a984708SDavid Chisnall for (__i_node** p = p2->beg_; p != p2->end_; ++p)
5127a984708SDavid Chisnall (*p)->__c_ = p2;
5137a984708SDavid Chisnall }
5147a984708SDavid Chisnall
5157a984708SDavid Chisnall void
__insert_i(void * __i)5167a984708SDavid Chisnall __libcpp_db::__insert_i(void* __i)
5177a984708SDavid Chisnall {
518d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
5197a984708SDavid Chisnall WLock _(mut());
520d72607e9SDimitry Andric #endif
5217a984708SDavid Chisnall __insert_iterator(__i);
5227a984708SDavid Chisnall }
5237a984708SDavid Chisnall
5247a984708SDavid Chisnall void
__add(__i_node * i)5257a984708SDavid Chisnall __c_node::__add(__i_node* i)
5267a984708SDavid Chisnall {
5277a984708SDavid Chisnall if (end_ == cap_)
5287a984708SDavid Chisnall {
52994e3ee44SDavid Chisnall size_t nc = 2*static_cast<size_t>(cap_ - beg_);
5307a984708SDavid Chisnall if (nc == 0)
5317a984708SDavid Chisnall nc = 1;
5324bab9fd9SDavid Chisnall __i_node** beg =
5334bab9fd9SDavid Chisnall static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
5347a984708SDavid Chisnall if (beg == nullptr)
535*aed8d94eSDimitry Andric __throw_bad_alloc();
536*aed8d94eSDimitry Andric
5377a984708SDavid Chisnall if (nc > 1)
5387a984708SDavid Chisnall memcpy(beg, beg_, nc/2*sizeof(__i_node*));
5397a984708SDavid Chisnall free(beg_);
5407a984708SDavid Chisnall beg_ = beg;
5417a984708SDavid Chisnall end_ = beg_ + nc/2;
5427a984708SDavid Chisnall cap_ = beg_ + nc;
5437a984708SDavid Chisnall }
5447a984708SDavid Chisnall *end_++ = i;
5457a984708SDavid Chisnall }
5467a984708SDavid Chisnall
5477a984708SDavid Chisnall // private api
5487a984708SDavid Chisnall
5497a984708SDavid Chisnall _LIBCPP_HIDDEN
5507a984708SDavid Chisnall __i_node*
__insert_iterator(void * __i)5517a984708SDavid Chisnall __libcpp_db::__insert_iterator(void* __i)
5527a984708SDavid Chisnall {
55394e3ee44SDavid Chisnall if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
5547a984708SDavid Chisnall {
55594e3ee44SDavid Chisnall size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
5564bab9fd9SDavid Chisnall __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
5577a984708SDavid Chisnall if (ibeg == nullptr)
558*aed8d94eSDimitry Andric __throw_bad_alloc();
559*aed8d94eSDimitry Andric
5607a984708SDavid Chisnall for (__i_node** p = __ibeg_; p != __iend_; ++p)
5617a984708SDavid Chisnall {
5627a984708SDavid Chisnall __i_node* q = *p;
5637a984708SDavid Chisnall while (q != nullptr)
5647a984708SDavid Chisnall {
5657a984708SDavid Chisnall size_t h = hash<void*>()(q->__i_) % nc;
5667a984708SDavid Chisnall __i_node* r = q->__next_;
5677a984708SDavid Chisnall q->__next_ = ibeg[h];
5687a984708SDavid Chisnall ibeg[h] = q;
5697a984708SDavid Chisnall q = r;
5707a984708SDavid Chisnall }
5717a984708SDavid Chisnall }
5727a984708SDavid Chisnall free(__ibeg_);
5737a984708SDavid Chisnall __ibeg_ = ibeg;
5747a984708SDavid Chisnall __iend_ = __ibeg_ + nc;
5757a984708SDavid Chisnall }
57694e3ee44SDavid Chisnall size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
5777a984708SDavid Chisnall __i_node* p = __ibeg_[hi];
5784bab9fd9SDavid Chisnall __i_node* r = __ibeg_[hi] =
5794bab9fd9SDavid Chisnall static_cast<__i_node*>(malloc(sizeof(__i_node)));
5807a984708SDavid Chisnall if (r == nullptr)
581*aed8d94eSDimitry Andric __throw_bad_alloc();
582*aed8d94eSDimitry Andric
5837a984708SDavid Chisnall ::new(r) __i_node(__i, p, nullptr);
5847a984708SDavid Chisnall ++__isz_;
5857a984708SDavid Chisnall return r;
5867a984708SDavid Chisnall }
5877a984708SDavid Chisnall
5887a984708SDavid Chisnall _LIBCPP_HIDDEN
5897a984708SDavid Chisnall __i_node*
__find_iterator(const void * __i) const5907a984708SDavid Chisnall __libcpp_db::__find_iterator(const void* __i) const
5917a984708SDavid Chisnall {
5927a984708SDavid Chisnall __i_node* r = nullptr;
5937a984708SDavid Chisnall if (__ibeg_ != __iend_)
5947a984708SDavid Chisnall {
59594e3ee44SDavid Chisnall size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
5967a984708SDavid Chisnall for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
5977a984708SDavid Chisnall {
5987a984708SDavid Chisnall if (nd->__i_ == __i)
5997a984708SDavid Chisnall {
6007a984708SDavid Chisnall r = nd;
6017a984708SDavid Chisnall break;
6027a984708SDavid Chisnall }
6037a984708SDavid Chisnall }
6047a984708SDavid Chisnall }
6057a984708SDavid Chisnall return r;
6067a984708SDavid Chisnall }
6077a984708SDavid Chisnall
6087a984708SDavid Chisnall _LIBCPP_HIDDEN
6097a984708SDavid Chisnall void
__remove(__i_node * p)6107a984708SDavid Chisnall __c_node::__remove(__i_node* p)
6117a984708SDavid Chisnall {
6127a984708SDavid Chisnall __i_node** r = find(beg_, end_, p);
6137a984708SDavid Chisnall _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
6147a984708SDavid Chisnall if (--end_ != r)
61594e3ee44SDavid Chisnall memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
6167a984708SDavid Chisnall }
6177a984708SDavid Chisnall
6187a984708SDavid Chisnall _LIBCPP_END_NAMESPACE_STD
619