xref: /freebsd-12.1/contrib/libc++/src/debug.cpp (revision cfdf2879)
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 #define _LIBCPP_DEBUG2 1
117a984708SDavid Chisnall #include "__config"
127a984708SDavid Chisnall #include "__debug"
137a984708SDavid Chisnall #include "functional"
147a984708SDavid Chisnall #include "algorithm"
157a984708SDavid Chisnall #include "__hash_table"
167a984708SDavid Chisnall #include "mutex"
177a984708SDavid Chisnall 
187a984708SDavid Chisnall _LIBCPP_BEGIN_NAMESPACE_STD
197a984708SDavid Chisnall 
207a984708SDavid Chisnall _LIBCPP_VISIBLE
217a984708SDavid Chisnall __libcpp_db*
227a984708SDavid Chisnall __get_db()
237a984708SDavid Chisnall {
247a984708SDavid Chisnall     static __libcpp_db db;
257a984708SDavid Chisnall     return &db;
26*cfdf2879SDavid Chisnall }
277a984708SDavid Chisnall 
287a984708SDavid Chisnall _LIBCPP_VISIBLE
297a984708SDavid Chisnall const __libcpp_db*
307a984708SDavid Chisnall __get_const_db()
317a984708SDavid Chisnall {
327a984708SDavid Chisnall     return __get_db();
337a984708SDavid Chisnall }
347a984708SDavid Chisnall 
357a984708SDavid Chisnall namespace
367a984708SDavid Chisnall {
377a984708SDavid Chisnall 
387a984708SDavid Chisnall typedef mutex mutex_type;
397a984708SDavid Chisnall typedef lock_guard<mutex_type> WLock;
407a984708SDavid Chisnall typedef lock_guard<mutex_type> RLock;
417a984708SDavid Chisnall 
427a984708SDavid Chisnall mutex_type&
437a984708SDavid Chisnall mut()
447a984708SDavid Chisnall {
457a984708SDavid Chisnall     static mutex_type m;
467a984708SDavid Chisnall     return m;
477a984708SDavid Chisnall }
487a984708SDavid Chisnall 
497a984708SDavid Chisnall }  // unnamed namespace
507a984708SDavid Chisnall 
517a984708SDavid Chisnall __i_node::~__i_node()
527a984708SDavid Chisnall {
537a984708SDavid Chisnall     if (__next_)
547a984708SDavid Chisnall     {
557a984708SDavid Chisnall         __next_->~__i_node();
567a984708SDavid Chisnall         free(__next_);
577a984708SDavid Chisnall     }
587a984708SDavid Chisnall }
597a984708SDavid Chisnall 
607a984708SDavid Chisnall __c_node::~__c_node()
617a984708SDavid Chisnall {
627a984708SDavid Chisnall     free(beg_);
637a984708SDavid Chisnall     if (__next_)
647a984708SDavid Chisnall     {
657a984708SDavid Chisnall         __next_->~__c_node();
667a984708SDavid Chisnall         free(__next_);
677a984708SDavid Chisnall     }
687a984708SDavid Chisnall }
697a984708SDavid Chisnall 
707a984708SDavid Chisnall __libcpp_db::__libcpp_db()
717a984708SDavid Chisnall     : __cbeg_(nullptr),
727a984708SDavid Chisnall       __cend_(nullptr),
737a984708SDavid Chisnall       __csz_(0),
747a984708SDavid Chisnall       __ibeg_(nullptr),
757a984708SDavid Chisnall       __iend_(nullptr),
767a984708SDavid Chisnall       __isz_(0)
777a984708SDavid Chisnall {
787a984708SDavid Chisnall }
797a984708SDavid Chisnall 
807a984708SDavid Chisnall __libcpp_db::~__libcpp_db()
817a984708SDavid Chisnall {
827a984708SDavid Chisnall     if (__cbeg_)
837a984708SDavid Chisnall     {
847a984708SDavid Chisnall         for (__c_node** p = __cbeg_; p != __cend_; ++p)
857a984708SDavid Chisnall         {
867a984708SDavid Chisnall             if (*p != nullptr)
877a984708SDavid Chisnall             {
887a984708SDavid Chisnall                 (*p)->~__c_node();
897a984708SDavid Chisnall                 free(*p);
907a984708SDavid Chisnall             }
917a984708SDavid Chisnall         }
927a984708SDavid Chisnall         free(__cbeg_);
937a984708SDavid Chisnall     }
947a984708SDavid Chisnall     if (__ibeg_)
957a984708SDavid Chisnall     {
967a984708SDavid Chisnall         for (__i_node** p = __ibeg_; p != __iend_; ++p)
977a984708SDavid Chisnall         {
987a984708SDavid Chisnall             if (*p != nullptr)
997a984708SDavid Chisnall             {
1007a984708SDavid Chisnall                 (*p)->~__i_node();
1017a984708SDavid Chisnall                 free(*p);
1027a984708SDavid Chisnall             }
1037a984708SDavid Chisnall         }
1047a984708SDavid Chisnall         free(__ibeg_);
1057a984708SDavid Chisnall     }
1067a984708SDavid Chisnall }
1077a984708SDavid Chisnall 
1087a984708SDavid Chisnall void*
1097a984708SDavid Chisnall __libcpp_db::__find_c_from_i(void* __i) const
1107a984708SDavid Chisnall {
1117a984708SDavid Chisnall     RLock _(mut());
1127a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
1137a984708SDavid Chisnall     _LIBCPP_ASSERT(i != nullptr, "iterator constructed in translation unit with debug mode not enabled."
1147a984708SDavid Chisnall                    "  #define _LIBCPP_DEBUG2 1 for that translation unit.");
1157a984708SDavid Chisnall     return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
1167a984708SDavid Chisnall }
1177a984708SDavid Chisnall 
1187a984708SDavid Chisnall void
1197a984708SDavid Chisnall __libcpp_db::__insert_ic(void* __i, const void* __c)
1207a984708SDavid Chisnall {
1217a984708SDavid Chisnall     WLock _(mut());
1227a984708SDavid Chisnall     __i_node* i = __insert_iterator(__i);
1237a984708SDavid Chisnall     const char* errmsg =
1247a984708SDavid Chisnall         "Container constructed in a translation unit with debug mode disabled."
1257a984708SDavid Chisnall         " But it is being used in a translation unit with debug mode enabled."
1267a984708SDavid Chisnall         " Enable it in the other translation unit with #define _LIBCPP_DEBUG2 1";
1277a984708SDavid Chisnall     _LIBCPP_ASSERT(__cbeg_ != __cend_, errmsg);
12894e3ee44SDavid Chisnall     size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
1297a984708SDavid Chisnall     __c_node* c = __cbeg_[hc];
1307a984708SDavid Chisnall     _LIBCPP_ASSERT(c != nullptr, errmsg);
1317a984708SDavid Chisnall     while (c->__c_ != __c)
1327a984708SDavid Chisnall     {
1337a984708SDavid Chisnall         c = c->__next_;
1347a984708SDavid Chisnall         _LIBCPP_ASSERT(c != nullptr, errmsg);
1357a984708SDavid Chisnall     }
1367a984708SDavid Chisnall     c->__add(i);
1377a984708SDavid Chisnall     i->__c_ = c;
1387a984708SDavid Chisnall }
1397a984708SDavid Chisnall 
1407a984708SDavid Chisnall __c_node*
1417a984708SDavid Chisnall __libcpp_db::__insert_c(void* __c)
1427a984708SDavid Chisnall {
1437a984708SDavid Chisnall     WLock _(mut());
14494e3ee44SDavid Chisnall     if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
1457a984708SDavid Chisnall     {
14694e3ee44SDavid Chisnall         size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
1477a984708SDavid Chisnall         __c_node** cbeg = (__c_node**)calloc(nc, sizeof(void*));
1487a984708SDavid Chisnall         if (cbeg == nullptr)
149936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
1507a984708SDavid Chisnall             throw bad_alloc();
151936e9439SDimitry Andric #else
152936e9439SDimitry Andric             abort();
153936e9439SDimitry Andric #endif
1547a984708SDavid Chisnall         for (__c_node** p = __cbeg_; p != __cend_; ++p)
1557a984708SDavid Chisnall         {
1567a984708SDavid Chisnall             __c_node* q = *p;
1577a984708SDavid Chisnall             while (q != nullptr)
1587a984708SDavid Chisnall             {
1597a984708SDavid Chisnall                 size_t h = hash<void*>()(q->__c_) % nc;
1607a984708SDavid Chisnall                 __c_node* r = q->__next_;
1617a984708SDavid Chisnall                 q->__next_ = cbeg[h];
1627a984708SDavid Chisnall                 cbeg[h] = q;
1637a984708SDavid Chisnall                 q = r;
1647a984708SDavid Chisnall             }
1657a984708SDavid Chisnall         }
1667a984708SDavid Chisnall         free(__cbeg_);
1677a984708SDavid Chisnall         __cbeg_ = cbeg;
1687a984708SDavid Chisnall         __cend_ = __cbeg_ + nc;
1697a984708SDavid Chisnall     }
17094e3ee44SDavid Chisnall     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
1717a984708SDavid Chisnall     __c_node* p = __cbeg_[hc];
1727a984708SDavid Chisnall     __c_node* r = __cbeg_[hc] = (__c_node*)malloc(sizeof(__c_node));
1737a984708SDavid Chisnall     if (__cbeg_[hc] == nullptr)
174936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
1757a984708SDavid Chisnall         throw bad_alloc();
176936e9439SDimitry Andric #else
177936e9439SDimitry Andric         abort();
178936e9439SDimitry Andric #endif
1797a984708SDavid Chisnall     r->__c_ = __c;
1807a984708SDavid Chisnall     r->__next_ = p;
1817a984708SDavid Chisnall     ++__csz_;
1827a984708SDavid Chisnall     return r;
1837a984708SDavid Chisnall }
1847a984708SDavid Chisnall 
1857a984708SDavid Chisnall void
1867a984708SDavid Chisnall __libcpp_db::__erase_i(void* __i)
1877a984708SDavid Chisnall {
1887a984708SDavid Chisnall     WLock _(mut());
1897a984708SDavid Chisnall     if (__ibeg_ != __iend_)
1907a984708SDavid Chisnall     {
19194e3ee44SDavid Chisnall         size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
1927a984708SDavid Chisnall         __i_node* p = __ibeg_[hi];
1937a984708SDavid Chisnall         if (p != nullptr)
1947a984708SDavid Chisnall         {
1957a984708SDavid Chisnall             __i_node* q = nullptr;
1967a984708SDavid Chisnall             while (p->__i_ != __i)
1977a984708SDavid Chisnall             {
1987a984708SDavid Chisnall                 q = p;
1997a984708SDavid Chisnall                 p = p->__next_;
2007a984708SDavid Chisnall                 if (p == nullptr)
2017a984708SDavid Chisnall                     return;
2027a984708SDavid Chisnall             }
2037a984708SDavid Chisnall             if (q == nullptr)
2047a984708SDavid Chisnall                 __ibeg_[hi] = p->__next_;
2057a984708SDavid Chisnall             else
2067a984708SDavid Chisnall                 q->__next_ = p->__next_;
2077a984708SDavid Chisnall             __c_node* c = p->__c_;
2087a984708SDavid Chisnall             free(p);
2097a984708SDavid Chisnall             --__isz_;
2107a984708SDavid Chisnall             if (c != nullptr)
2117a984708SDavid Chisnall                 c->__remove(p);
2127a984708SDavid Chisnall         }
2137a984708SDavid Chisnall     }
2147a984708SDavid Chisnall }
2157a984708SDavid Chisnall 
2167a984708SDavid Chisnall void
2177a984708SDavid Chisnall __libcpp_db::__invalidate_all(void* __c)
2187a984708SDavid Chisnall {
2197a984708SDavid Chisnall     WLock _(mut());
22094e3ee44SDavid Chisnall     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2217a984708SDavid Chisnall     __c_node* p = __cbeg_[hc];
2227a984708SDavid Chisnall     _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __invalidate_all A");
2237a984708SDavid Chisnall     while (p->__c_ != __c)
2247a984708SDavid Chisnall     {
2257a984708SDavid Chisnall         p = p->__next_;
2267a984708SDavid Chisnall         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __invalidate_all B");
2277a984708SDavid Chisnall     }
2287a984708SDavid Chisnall     while (p->end_ != p->beg_)
2297a984708SDavid Chisnall     {
2307a984708SDavid Chisnall         --p->end_;
2317a984708SDavid Chisnall         (*p->end_)->__c_ = nullptr;
2327a984708SDavid Chisnall     }
2337a984708SDavid Chisnall }
2347a984708SDavid Chisnall 
2357a984708SDavid Chisnall __c_node*
2367a984708SDavid Chisnall __libcpp_db::__find_c_and_lock(void* __c) const
2377a984708SDavid Chisnall {
2387a984708SDavid Chisnall     mut().lock();
23994e3ee44SDavid Chisnall     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2407a984708SDavid Chisnall     __c_node* p = __cbeg_[hc];
2417a984708SDavid Chisnall     _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c_and_lock A");
2427a984708SDavid Chisnall     while (p->__c_ != __c)
2437a984708SDavid Chisnall     {
2447a984708SDavid Chisnall         p = p->__next_;
2457a984708SDavid Chisnall         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c_and_lock B");
2467a984708SDavid Chisnall     }
2477a984708SDavid Chisnall     return p;
2487a984708SDavid Chisnall }
2497a984708SDavid Chisnall 
2507a984708SDavid Chisnall __c_node*
2517a984708SDavid Chisnall __libcpp_db::__find_c(void* __c) const
2527a984708SDavid Chisnall {
25394e3ee44SDavid Chisnall     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2547a984708SDavid Chisnall     __c_node* p = __cbeg_[hc];
2557a984708SDavid Chisnall     _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
2567a984708SDavid Chisnall     while (p->__c_ != __c)
2577a984708SDavid Chisnall     {
2587a984708SDavid Chisnall         p = p->__next_;
2597a984708SDavid Chisnall         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
2607a984708SDavid Chisnall     }
2617a984708SDavid Chisnall     return p;
2627a984708SDavid Chisnall }
2637a984708SDavid Chisnall 
2647a984708SDavid Chisnall void
2657a984708SDavid Chisnall __libcpp_db::unlock() const
2667a984708SDavid Chisnall {
2677a984708SDavid Chisnall     mut().unlock();
2687a984708SDavid Chisnall }
2697a984708SDavid Chisnall 
2707a984708SDavid Chisnall void
2717a984708SDavid Chisnall __libcpp_db::__erase_c(void* __c)
2727a984708SDavid Chisnall {
2737a984708SDavid Chisnall     WLock _(mut());
27494e3ee44SDavid Chisnall     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2757a984708SDavid Chisnall     __c_node* p = __cbeg_[hc];
2767a984708SDavid Chisnall     __c_node* q = nullptr;
2777a984708SDavid Chisnall     _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
2787a984708SDavid Chisnall     while (p->__c_ != __c)
2797a984708SDavid Chisnall     {
2807a984708SDavid Chisnall         q = p;
2817a984708SDavid Chisnall         p = p->__next_;
2827a984708SDavid Chisnall         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
2837a984708SDavid Chisnall     }
2847a984708SDavid Chisnall     if (q == nullptr)
2857a984708SDavid Chisnall         __cbeg_[hc] = p->__next_;
2867a984708SDavid Chisnall     else
2877a984708SDavid Chisnall         q->__next_ = p->__next_;
2887a984708SDavid Chisnall     while (p->end_ != p->beg_)
2897a984708SDavid Chisnall     {
2907a984708SDavid Chisnall         --p->end_;
2917a984708SDavid Chisnall         (*p->end_)->__c_ = nullptr;
2927a984708SDavid Chisnall     }
2937a984708SDavid Chisnall     free(p->beg_);
2947a984708SDavid Chisnall     free(p);
2957a984708SDavid Chisnall     --__csz_;
2967a984708SDavid Chisnall }
2977a984708SDavid Chisnall 
2987a984708SDavid Chisnall void
2997a984708SDavid Chisnall __libcpp_db::__iterator_copy(void* __i, const void* __i0)
3007a984708SDavid Chisnall {
3017a984708SDavid Chisnall     WLock _(mut());
3027a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3037a984708SDavid Chisnall     __i_node* i0 = __find_iterator(__i0);
3047a984708SDavid Chisnall     __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
3057a984708SDavid Chisnall     if (i == nullptr && c0 != nullptr)
3067a984708SDavid Chisnall         i = __insert_iterator(__i);
3077a984708SDavid Chisnall     __c_node* c = i != nullptr ? i->__c_ : nullptr;
3087a984708SDavid Chisnall     if (c != c0)
3097a984708SDavid Chisnall     {
3107a984708SDavid Chisnall         if (c != nullptr)
3117a984708SDavid Chisnall             c->__remove(i);
3127a984708SDavid Chisnall         if (i != nullptr)
3137a984708SDavid Chisnall         {
3147a984708SDavid Chisnall             i->__c_ = nullptr;
3157a984708SDavid Chisnall             if (c0 != nullptr)
3167a984708SDavid Chisnall             {
3177a984708SDavid Chisnall                 i->__c_ = c0;
3187a984708SDavid Chisnall                 i->__c_->__add(i);
3197a984708SDavid Chisnall             }
3207a984708SDavid Chisnall         }
3217a984708SDavid Chisnall     }
3227a984708SDavid Chisnall }
3237a984708SDavid Chisnall 
3247a984708SDavid Chisnall bool
3257a984708SDavid Chisnall __libcpp_db::__dereferenceable(const void* __i) const
3267a984708SDavid Chisnall {
3277a984708SDavid Chisnall     RLock _(mut());
3287a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3297a984708SDavid Chisnall     return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
3307a984708SDavid Chisnall }
3317a984708SDavid Chisnall 
3327a984708SDavid Chisnall bool
3337a984708SDavid Chisnall __libcpp_db::__decrementable(const void* __i) const
3347a984708SDavid Chisnall {
3357a984708SDavid Chisnall     RLock _(mut());
3367a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3377a984708SDavid Chisnall     return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
3387a984708SDavid Chisnall }
3397a984708SDavid Chisnall 
3407a984708SDavid Chisnall bool
3417a984708SDavid Chisnall __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
3427a984708SDavid Chisnall {
3437a984708SDavid Chisnall     RLock _(mut());
3447a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3457a984708SDavid Chisnall     return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
3467a984708SDavid Chisnall }
3477a984708SDavid Chisnall 
3487a984708SDavid Chisnall bool
3497a984708SDavid Chisnall __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
3507a984708SDavid Chisnall {
3517a984708SDavid Chisnall     RLock _(mut());
3527a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3537a984708SDavid Chisnall     return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
3547a984708SDavid Chisnall }
3557a984708SDavid Chisnall 
3567a984708SDavid Chisnall bool
3577a984708SDavid Chisnall __libcpp_db::__comparable(const void* __i, const void* __j) const
3587a984708SDavid Chisnall {
3597a984708SDavid Chisnall     RLock _(mut());
3607a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3617a984708SDavid Chisnall     __i_node* j = __find_iterator(__j);
3627a984708SDavid Chisnall     __c_node* ci = i != nullptr ? i->__c_ : nullptr;
3637a984708SDavid Chisnall     __c_node* cj = j != nullptr ? j->__c_ : nullptr;
3647a984708SDavid Chisnall     return ci != nullptr && ci == cj;
3657a984708SDavid Chisnall }
3667a984708SDavid Chisnall 
3677a984708SDavid Chisnall void
3687a984708SDavid Chisnall __libcpp_db::swap(void* c1, void* c2)
3697a984708SDavid Chisnall {
3707a984708SDavid Chisnall     WLock _(mut());
37194e3ee44SDavid Chisnall     size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
3727a984708SDavid Chisnall     __c_node* p1 = __cbeg_[hc];
3737a984708SDavid Chisnall     _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
3747a984708SDavid Chisnall     while (p1->__c_ != c1)
3757a984708SDavid Chisnall     {
3767a984708SDavid Chisnall         p1 = p1->__next_;
3777a984708SDavid Chisnall         _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
3787a984708SDavid Chisnall     }
37994e3ee44SDavid Chisnall     hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
3807a984708SDavid Chisnall     __c_node* p2 = __cbeg_[hc];
3817a984708SDavid Chisnall     _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
3827a984708SDavid Chisnall     while (p2->__c_ != c2)
3837a984708SDavid Chisnall     {
3847a984708SDavid Chisnall         p2 = p2->__next_;
3857a984708SDavid Chisnall         _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
3867a984708SDavid Chisnall     }
3877a984708SDavid Chisnall     std::swap(p1->beg_, p2->beg_);
3887a984708SDavid Chisnall     std::swap(p1->end_, p2->end_);
3897a984708SDavid Chisnall     std::swap(p1->cap_, p2->cap_);
3907a984708SDavid Chisnall     for (__i_node** p = p1->beg_; p != p1->end_; ++p)
3917a984708SDavid Chisnall         (*p)->__c_ = p1;
3927a984708SDavid Chisnall     for (__i_node** p = p2->beg_; p != p2->end_; ++p)
3937a984708SDavid Chisnall         (*p)->__c_ = p2;
3947a984708SDavid Chisnall }
3957a984708SDavid Chisnall 
3967a984708SDavid Chisnall void
3977a984708SDavid Chisnall __libcpp_db::__insert_i(void* __i)
3987a984708SDavid Chisnall {
3997a984708SDavid Chisnall     WLock _(mut());
4007a984708SDavid Chisnall     __insert_iterator(__i);
4017a984708SDavid Chisnall }
4027a984708SDavid Chisnall 
4037a984708SDavid Chisnall void
4047a984708SDavid Chisnall __c_node::__add(__i_node* i)
4057a984708SDavid Chisnall {
4067a984708SDavid Chisnall     if (end_ == cap_)
4077a984708SDavid Chisnall     {
40894e3ee44SDavid Chisnall         size_t nc = 2*static_cast<size_t>(cap_ - beg_);
4097a984708SDavid Chisnall         if (nc == 0)
4107a984708SDavid Chisnall             nc = 1;
4117a984708SDavid Chisnall         __i_node** beg = (__i_node**)malloc(nc * sizeof(__i_node*));
4127a984708SDavid Chisnall         if (beg == nullptr)
413936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
4147a984708SDavid Chisnall             throw bad_alloc();
415936e9439SDimitry Andric #else
416936e9439SDimitry Andric             abort();
417936e9439SDimitry Andric #endif
4187a984708SDavid Chisnall         if (nc > 1)
4197a984708SDavid Chisnall             memcpy(beg, beg_, nc/2*sizeof(__i_node*));
4207a984708SDavid Chisnall         free(beg_);
4217a984708SDavid Chisnall         beg_ = beg;
4227a984708SDavid Chisnall         end_ = beg_ + nc/2;
4237a984708SDavid Chisnall         cap_ = beg_ + nc;
4247a984708SDavid Chisnall     }
4257a984708SDavid Chisnall     *end_++ = i;
4267a984708SDavid Chisnall }
4277a984708SDavid Chisnall 
4287a984708SDavid Chisnall // private api
4297a984708SDavid Chisnall 
4307a984708SDavid Chisnall _LIBCPP_HIDDEN
4317a984708SDavid Chisnall __i_node*
4327a984708SDavid Chisnall __libcpp_db::__insert_iterator(void* __i)
4337a984708SDavid Chisnall {
43494e3ee44SDavid Chisnall     if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
4357a984708SDavid Chisnall     {
43694e3ee44SDavid Chisnall         size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
4377a984708SDavid Chisnall         __i_node** ibeg = (__i_node**)calloc(nc, sizeof(void*));
4387a984708SDavid Chisnall         if (ibeg == nullptr)
439936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
4407a984708SDavid Chisnall             throw bad_alloc();
441936e9439SDimitry Andric #else
442936e9439SDimitry Andric             abort();
443936e9439SDimitry Andric #endif
4447a984708SDavid Chisnall         for (__i_node** p = __ibeg_; p != __iend_; ++p)
4457a984708SDavid Chisnall         {
4467a984708SDavid Chisnall             __i_node* q = *p;
4477a984708SDavid Chisnall             while (q != nullptr)
4487a984708SDavid Chisnall             {
4497a984708SDavid Chisnall                 size_t h = hash<void*>()(q->__i_) % nc;
4507a984708SDavid Chisnall                 __i_node* r = q->__next_;
4517a984708SDavid Chisnall                 q->__next_ = ibeg[h];
4527a984708SDavid Chisnall                 ibeg[h] = q;
4537a984708SDavid Chisnall                 q = r;
4547a984708SDavid Chisnall             }
4557a984708SDavid Chisnall         }
4567a984708SDavid Chisnall         free(__ibeg_);
4577a984708SDavid Chisnall         __ibeg_ = ibeg;
4587a984708SDavid Chisnall         __iend_ = __ibeg_ + nc;
4597a984708SDavid Chisnall     }
46094e3ee44SDavid Chisnall     size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
4617a984708SDavid Chisnall     __i_node* p = __ibeg_[hi];
4627a984708SDavid Chisnall     __i_node* r = __ibeg_[hi] = (__i_node*)malloc(sizeof(__i_node));
4637a984708SDavid Chisnall     if (r == nullptr)
464936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
4657a984708SDavid Chisnall         throw bad_alloc();
466936e9439SDimitry Andric #else
467936e9439SDimitry Andric         abort();
468936e9439SDimitry Andric #endif
4697a984708SDavid Chisnall     ::new(r) __i_node(__i, p, nullptr);
4707a984708SDavid Chisnall     ++__isz_;
4717a984708SDavid Chisnall     return r;
4727a984708SDavid Chisnall }
4737a984708SDavid Chisnall 
4747a984708SDavid Chisnall _LIBCPP_HIDDEN
4757a984708SDavid Chisnall __i_node*
4767a984708SDavid Chisnall __libcpp_db::__find_iterator(const void* __i) const
4777a984708SDavid Chisnall {
4787a984708SDavid Chisnall     __i_node* r = nullptr;
4797a984708SDavid Chisnall     if (__ibeg_ != __iend_)
4807a984708SDavid Chisnall     {
48194e3ee44SDavid Chisnall         size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
4827a984708SDavid Chisnall         for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
4837a984708SDavid Chisnall         {
4847a984708SDavid Chisnall             if (nd->__i_ == __i)
4857a984708SDavid Chisnall             {
4867a984708SDavid Chisnall                 r = nd;
4877a984708SDavid Chisnall                 break;
4887a984708SDavid Chisnall             }
4897a984708SDavid Chisnall         }
4907a984708SDavid Chisnall     }
4917a984708SDavid Chisnall     return r;
4927a984708SDavid Chisnall }
4937a984708SDavid Chisnall 
4947a984708SDavid Chisnall _LIBCPP_HIDDEN
4957a984708SDavid Chisnall void
4967a984708SDavid Chisnall __c_node::__remove(__i_node* p)
4977a984708SDavid Chisnall {
4987a984708SDavid Chisnall     __i_node** r = find(beg_, end_, p);
4997a984708SDavid Chisnall     _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
5007a984708SDavid Chisnall     if (--end_ != r)
50194e3ee44SDavid Chisnall         memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
5027a984708SDavid Chisnall }
5037a984708SDavid Chisnall 
5047a984708SDavid Chisnall _LIBCPP_END_NAMESPACE_STD
505