xref: /freebsd-12.1/contrib/libc++/src/debug.cpp (revision 854fa44b)
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 
104f7ab58eSDimitry Andric #define _LIBCPP_DEBUG 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 
201bf9f7c1SDimitry Andric _LIBCPP_FUNC_VIS
217a984708SDavid Chisnall __libcpp_db*
227a984708SDavid Chisnall __get_db()
237a984708SDavid Chisnall {
247a984708SDavid Chisnall     static __libcpp_db db;
257a984708SDavid Chisnall     return &db;
26cfdf2879SDavid Chisnall }
277a984708SDavid Chisnall 
281bf9f7c1SDimitry Andric _LIBCPP_FUNC_VIS
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 
38d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
397a984708SDavid Chisnall typedef mutex mutex_type;
407a984708SDavid Chisnall typedef lock_guard<mutex_type> WLock;
417a984708SDavid Chisnall typedef lock_guard<mutex_type> RLock;
427a984708SDavid Chisnall 
437a984708SDavid Chisnall mutex_type&
447a984708SDavid Chisnall mut()
457a984708SDavid Chisnall {
467a984708SDavid Chisnall     static mutex_type m;
477a984708SDavid Chisnall     return m;
487a984708SDavid Chisnall }
49d72607e9SDimitry Andric #endif // !_LIBCPP_HAS_NO_THREADS
507a984708SDavid Chisnall 
517a984708SDavid Chisnall }  // unnamed namespace
527a984708SDavid Chisnall 
537a984708SDavid Chisnall __i_node::~__i_node()
547a984708SDavid Chisnall {
557a984708SDavid Chisnall     if (__next_)
567a984708SDavid Chisnall     {
577a984708SDavid Chisnall         __next_->~__i_node();
587a984708SDavid Chisnall         free(__next_);
597a984708SDavid Chisnall     }
607a984708SDavid Chisnall }
617a984708SDavid Chisnall 
627a984708SDavid Chisnall __c_node::~__c_node()
637a984708SDavid Chisnall {
647a984708SDavid Chisnall     free(beg_);
657a984708SDavid Chisnall     if (__next_)
667a984708SDavid Chisnall     {
677a984708SDavid Chisnall         __next_->~__c_node();
687a984708SDavid Chisnall         free(__next_);
697a984708SDavid Chisnall     }
707a984708SDavid Chisnall }
717a984708SDavid Chisnall 
727a984708SDavid Chisnall __libcpp_db::__libcpp_db()
737a984708SDavid Chisnall     : __cbeg_(nullptr),
747a984708SDavid Chisnall       __cend_(nullptr),
757a984708SDavid Chisnall       __csz_(0),
767a984708SDavid Chisnall       __ibeg_(nullptr),
777a984708SDavid Chisnall       __iend_(nullptr),
787a984708SDavid Chisnall       __isz_(0)
797a984708SDavid Chisnall {
807a984708SDavid Chisnall }
817a984708SDavid Chisnall 
827a984708SDavid Chisnall __libcpp_db::~__libcpp_db()
837a984708SDavid Chisnall {
847a984708SDavid Chisnall     if (__cbeg_)
857a984708SDavid Chisnall     {
867a984708SDavid Chisnall         for (__c_node** p = __cbeg_; p != __cend_; ++p)
877a984708SDavid Chisnall         {
887a984708SDavid Chisnall             if (*p != nullptr)
897a984708SDavid Chisnall             {
907a984708SDavid Chisnall                 (*p)->~__c_node();
917a984708SDavid Chisnall                 free(*p);
927a984708SDavid Chisnall             }
937a984708SDavid Chisnall         }
947a984708SDavid Chisnall         free(__cbeg_);
957a984708SDavid Chisnall     }
967a984708SDavid Chisnall     if (__ibeg_)
977a984708SDavid Chisnall     {
987a984708SDavid Chisnall         for (__i_node** p = __ibeg_; p != __iend_; ++p)
997a984708SDavid Chisnall         {
1007a984708SDavid Chisnall             if (*p != nullptr)
1017a984708SDavid Chisnall             {
1027a984708SDavid Chisnall                 (*p)->~__i_node();
1037a984708SDavid Chisnall                 free(*p);
1047a984708SDavid Chisnall             }
1057a984708SDavid Chisnall         }
1067a984708SDavid Chisnall         free(__ibeg_);
1077a984708SDavid Chisnall     }
1087a984708SDavid Chisnall }
1097a984708SDavid Chisnall 
1107a984708SDavid Chisnall void*
1117a984708SDavid Chisnall __libcpp_db::__find_c_from_i(void* __i) const
1127a984708SDavid Chisnall {
113d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1147a984708SDavid Chisnall     RLock _(mut());
115d72607e9SDimitry Andric #endif
1167a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
1171bf9f7c1SDimitry Andric     _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
1187a984708SDavid Chisnall     return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
1197a984708SDavid Chisnall }
1207a984708SDavid Chisnall 
1217a984708SDavid Chisnall void
1227a984708SDavid Chisnall __libcpp_db::__insert_ic(void* __i, const void* __c)
1237a984708SDavid Chisnall {
124d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1257a984708SDavid Chisnall     WLock _(mut());
126d72607e9SDimitry Andric #endif
1274f7ab58eSDimitry Andric     if (__cbeg_ == __cend_)
1284f7ab58eSDimitry Andric         return;
12994e3ee44SDavid Chisnall     size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
1307a984708SDavid Chisnall     __c_node* c = __cbeg_[hc];
1314f7ab58eSDimitry Andric     if (c == nullptr)
1324f7ab58eSDimitry Andric         return;
1337a984708SDavid Chisnall     while (c->__c_ != __c)
1347a984708SDavid Chisnall     {
1357a984708SDavid Chisnall         c = c->__next_;
1364f7ab58eSDimitry Andric         if (c == nullptr)
1374f7ab58eSDimitry Andric             return;
1387a984708SDavid Chisnall     }
1394f7ab58eSDimitry Andric     __i_node* i = __insert_iterator(__i);
1407a984708SDavid Chisnall     c->__add(i);
1417a984708SDavid Chisnall     i->__c_ = c;
1427a984708SDavid Chisnall }
1437a984708SDavid Chisnall 
1447a984708SDavid Chisnall __c_node*
1457a984708SDavid Chisnall __libcpp_db::__insert_c(void* __c)
1467a984708SDavid Chisnall {
147d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1487a984708SDavid Chisnall     WLock _(mut());
149d72607e9SDimitry Andric #endif
15094e3ee44SDavid Chisnall     if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
1517a984708SDavid Chisnall     {
15294e3ee44SDavid Chisnall         size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
1534bab9fd9SDavid Chisnall         __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
1547a984708SDavid Chisnall         if (cbeg == nullptr)
155936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
1567a984708SDavid Chisnall             throw bad_alloc();
157936e9439SDimitry Andric #else
158936e9439SDimitry Andric             abort();
159936e9439SDimitry Andric #endif
1607a984708SDavid Chisnall         for (__c_node** p = __cbeg_; p != __cend_; ++p)
1617a984708SDavid Chisnall         {
1627a984708SDavid Chisnall             __c_node* q = *p;
1637a984708SDavid Chisnall             while (q != nullptr)
1647a984708SDavid Chisnall             {
1657a984708SDavid Chisnall                 size_t h = hash<void*>()(q->__c_) % nc;
1667a984708SDavid Chisnall                 __c_node* r = q->__next_;
1677a984708SDavid Chisnall                 q->__next_ = cbeg[h];
1687a984708SDavid Chisnall                 cbeg[h] = q;
1697a984708SDavid Chisnall                 q = r;
1707a984708SDavid Chisnall             }
1717a984708SDavid Chisnall         }
1727a984708SDavid Chisnall         free(__cbeg_);
1737a984708SDavid Chisnall         __cbeg_ = cbeg;
1747a984708SDavid Chisnall         __cend_ = __cbeg_ + nc;
1757a984708SDavid Chisnall     }
17694e3ee44SDavid Chisnall     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
1777a984708SDavid Chisnall     __c_node* p = __cbeg_[hc];
1784bab9fd9SDavid Chisnall     __c_node* r = __cbeg_[hc] =
1794bab9fd9SDavid Chisnall       static_cast<__c_node*>(malloc(sizeof(__c_node)));
1807a984708SDavid Chisnall     if (__cbeg_[hc] == nullptr)
181936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
1827a984708SDavid Chisnall         throw bad_alloc();
183936e9439SDimitry Andric #else
184936e9439SDimitry Andric         abort();
185936e9439SDimitry Andric #endif
1867a984708SDavid Chisnall     r->__c_ = __c;
1877a984708SDavid Chisnall     r->__next_ = p;
1887a984708SDavid Chisnall     ++__csz_;
1897a984708SDavid Chisnall     return r;
1907a984708SDavid Chisnall }
1917a984708SDavid Chisnall 
1927a984708SDavid Chisnall void
1937a984708SDavid Chisnall __libcpp_db::__erase_i(void* __i)
1947a984708SDavid Chisnall {
195d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1967a984708SDavid Chisnall     WLock _(mut());
197d72607e9SDimitry Andric #endif
1987a984708SDavid Chisnall     if (__ibeg_ != __iend_)
1997a984708SDavid Chisnall     {
20094e3ee44SDavid Chisnall         size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
2017a984708SDavid Chisnall         __i_node* p = __ibeg_[hi];
2027a984708SDavid Chisnall         if (p != nullptr)
2037a984708SDavid Chisnall         {
2047a984708SDavid Chisnall             __i_node* q = nullptr;
2057a984708SDavid Chisnall             while (p->__i_ != __i)
2067a984708SDavid Chisnall             {
2077a984708SDavid Chisnall                 q = p;
2087a984708SDavid Chisnall                 p = p->__next_;
2097a984708SDavid Chisnall                 if (p == nullptr)
2107a984708SDavid Chisnall                     return;
2117a984708SDavid Chisnall             }
2127a984708SDavid Chisnall             if (q == nullptr)
2137a984708SDavid Chisnall                 __ibeg_[hi] = p->__next_;
2147a984708SDavid Chisnall             else
2157a984708SDavid Chisnall                 q->__next_ = p->__next_;
2167a984708SDavid Chisnall             __c_node* c = p->__c_;
2177a984708SDavid Chisnall             --__isz_;
2187a984708SDavid Chisnall             if (c != nullptr)
2197a984708SDavid Chisnall                 c->__remove(p);
220*854fa44bSDimitry Andric             free(p);
2217a984708SDavid Chisnall         }
2227a984708SDavid Chisnall     }
2237a984708SDavid Chisnall }
2247a984708SDavid Chisnall 
2257a984708SDavid Chisnall void
2267a984708SDavid Chisnall __libcpp_db::__invalidate_all(void* __c)
2277a984708SDavid Chisnall {
228d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2297a984708SDavid Chisnall     WLock _(mut());
230d72607e9SDimitry Andric #endif
2314f7ab58eSDimitry Andric     if (__cend_ != __cbeg_)
2324f7ab58eSDimitry Andric     {
23394e3ee44SDavid Chisnall         size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2347a984708SDavid Chisnall         __c_node* p = __cbeg_[hc];
2354f7ab58eSDimitry Andric         if (p == nullptr)
2364f7ab58eSDimitry Andric             return;
2377a984708SDavid Chisnall         while (p->__c_ != __c)
2387a984708SDavid Chisnall         {
2397a984708SDavid Chisnall             p = p->__next_;
2404f7ab58eSDimitry Andric             if (p == nullptr)
2414f7ab58eSDimitry Andric                 return;
2427a984708SDavid Chisnall         }
2437a984708SDavid Chisnall         while (p->end_ != p->beg_)
2447a984708SDavid Chisnall         {
2457a984708SDavid Chisnall             --p->end_;
2467a984708SDavid Chisnall             (*p->end_)->__c_ = nullptr;
2477a984708SDavid Chisnall         }
2487a984708SDavid Chisnall     }
2494f7ab58eSDimitry Andric }
2507a984708SDavid Chisnall 
2517a984708SDavid Chisnall __c_node*
2527a984708SDavid Chisnall __libcpp_db::__find_c_and_lock(void* __c) const
2537a984708SDavid Chisnall {
254d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2557a984708SDavid Chisnall     mut().lock();
256d72607e9SDimitry Andric #endif
2574f7ab58eSDimitry Andric     if (__cend_ == __cbeg_)
2584f7ab58eSDimitry Andric     {
259d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2604f7ab58eSDimitry Andric         mut().unlock();
261d72607e9SDimitry Andric #endif
2624f7ab58eSDimitry Andric         return nullptr;
2634f7ab58eSDimitry Andric     }
26494e3ee44SDavid Chisnall     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2657a984708SDavid Chisnall     __c_node* p = __cbeg_[hc];
2664f7ab58eSDimitry Andric     if (p == nullptr)
2674f7ab58eSDimitry Andric     {
268d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2694f7ab58eSDimitry Andric         mut().unlock();
270d72607e9SDimitry Andric #endif
2714f7ab58eSDimitry Andric         return nullptr;
2724f7ab58eSDimitry Andric     }
2737a984708SDavid Chisnall     while (p->__c_ != __c)
2747a984708SDavid Chisnall     {
2757a984708SDavid Chisnall         p = p->__next_;
2764f7ab58eSDimitry Andric         if (p == nullptr)
2774f7ab58eSDimitry Andric         {
278d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2794f7ab58eSDimitry Andric             mut().unlock();
280d72607e9SDimitry Andric #endif
2814f7ab58eSDimitry Andric             return nullptr;
2824f7ab58eSDimitry Andric         }
2837a984708SDavid Chisnall     }
2847a984708SDavid Chisnall     return p;
2857a984708SDavid Chisnall }
2867a984708SDavid Chisnall 
2877a984708SDavid Chisnall __c_node*
2887a984708SDavid Chisnall __libcpp_db::__find_c(void* __c) const
2897a984708SDavid Chisnall {
29094e3ee44SDavid Chisnall     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2917a984708SDavid Chisnall     __c_node* p = __cbeg_[hc];
2927a984708SDavid Chisnall     _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
2937a984708SDavid Chisnall     while (p->__c_ != __c)
2947a984708SDavid Chisnall     {
2957a984708SDavid Chisnall         p = p->__next_;
2967a984708SDavid Chisnall         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
2977a984708SDavid Chisnall     }
2987a984708SDavid Chisnall     return p;
2997a984708SDavid Chisnall }
3007a984708SDavid Chisnall 
3017a984708SDavid Chisnall void
3027a984708SDavid Chisnall __libcpp_db::unlock() const
3037a984708SDavid Chisnall {
304d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3057a984708SDavid Chisnall     mut().unlock();
306d72607e9SDimitry Andric #endif
3077a984708SDavid Chisnall }
3087a984708SDavid Chisnall 
3097a984708SDavid Chisnall void
3107a984708SDavid Chisnall __libcpp_db::__erase_c(void* __c)
3117a984708SDavid Chisnall {
312d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3137a984708SDavid Chisnall     WLock _(mut());
314d72607e9SDimitry Andric #endif
3154f7ab58eSDimitry Andric     if (__cend_ != __cbeg_)
3164f7ab58eSDimitry Andric     {
31794e3ee44SDavid Chisnall         size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
3187a984708SDavid Chisnall         __c_node* p = __cbeg_[hc];
3194f7ab58eSDimitry Andric         if (p == nullptr)
3204f7ab58eSDimitry Andric             return;
3217a984708SDavid Chisnall         __c_node* q = nullptr;
3227a984708SDavid Chisnall         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
3237a984708SDavid Chisnall         while (p->__c_ != __c)
3247a984708SDavid Chisnall         {
3257a984708SDavid Chisnall             q = p;
3267a984708SDavid Chisnall             p = p->__next_;
3274f7ab58eSDimitry Andric             if (p == nullptr)
3284f7ab58eSDimitry Andric                 return;
3297a984708SDavid Chisnall             _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
3307a984708SDavid Chisnall         }
3317a984708SDavid Chisnall         if (q == nullptr)
3327a984708SDavid Chisnall             __cbeg_[hc] = p->__next_;
3337a984708SDavid Chisnall         else
3347a984708SDavid Chisnall             q->__next_ = p->__next_;
3357a984708SDavid Chisnall         while (p->end_ != p->beg_)
3367a984708SDavid Chisnall         {
3377a984708SDavid Chisnall             --p->end_;
3387a984708SDavid Chisnall             (*p->end_)->__c_ = nullptr;
3397a984708SDavid Chisnall         }
3407a984708SDavid Chisnall         free(p->beg_);
3417a984708SDavid Chisnall         free(p);
3427a984708SDavid Chisnall         --__csz_;
3437a984708SDavid Chisnall     }
3444f7ab58eSDimitry Andric }
3457a984708SDavid Chisnall 
3467a984708SDavid Chisnall void
3477a984708SDavid Chisnall __libcpp_db::__iterator_copy(void* __i, const void* __i0)
3487a984708SDavid Chisnall {
349d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3507a984708SDavid Chisnall     WLock _(mut());
351d72607e9SDimitry Andric #endif
3527a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3537a984708SDavid Chisnall     __i_node* i0 = __find_iterator(__i0);
3547a984708SDavid Chisnall     __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
3551bf9f7c1SDimitry Andric     if (i == nullptr && i0 != nullptr)
3567a984708SDavid Chisnall         i = __insert_iterator(__i);
3577a984708SDavid Chisnall     __c_node* c = i != nullptr ? i->__c_ : nullptr;
3587a984708SDavid Chisnall     if (c != c0)
3597a984708SDavid Chisnall     {
3607a984708SDavid Chisnall         if (c != nullptr)
3617a984708SDavid Chisnall             c->__remove(i);
3627a984708SDavid Chisnall         if (i != nullptr)
3637a984708SDavid Chisnall         {
3647a984708SDavid Chisnall             i->__c_ = nullptr;
3657a984708SDavid Chisnall             if (c0 != nullptr)
3667a984708SDavid Chisnall             {
3677a984708SDavid Chisnall                 i->__c_ = c0;
3687a984708SDavid Chisnall                 i->__c_->__add(i);
3697a984708SDavid Chisnall             }
3707a984708SDavid Chisnall         }
3717a984708SDavid Chisnall     }
3727a984708SDavid Chisnall }
3737a984708SDavid Chisnall 
3747a984708SDavid Chisnall bool
3757a984708SDavid Chisnall __libcpp_db::__dereferenceable(const void* __i) const
3767a984708SDavid Chisnall {
377d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3787a984708SDavid Chisnall     RLock _(mut());
379d72607e9SDimitry Andric #endif
3807a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3817a984708SDavid Chisnall     return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
3827a984708SDavid Chisnall }
3837a984708SDavid Chisnall 
3847a984708SDavid Chisnall bool
3857a984708SDavid Chisnall __libcpp_db::__decrementable(const void* __i) const
3867a984708SDavid Chisnall {
387d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3887a984708SDavid Chisnall     RLock _(mut());
389d72607e9SDimitry Andric #endif
3907a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
3917a984708SDavid Chisnall     return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
3927a984708SDavid Chisnall }
3937a984708SDavid Chisnall 
3947a984708SDavid Chisnall bool
3957a984708SDavid Chisnall __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
3967a984708SDavid Chisnall {
397d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3987a984708SDavid Chisnall     RLock _(mut());
399d72607e9SDimitry Andric #endif
4007a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
4017a984708SDavid Chisnall     return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
4027a984708SDavid Chisnall }
4037a984708SDavid Chisnall 
4047a984708SDavid Chisnall bool
4057a984708SDavid Chisnall __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
4067a984708SDavid Chisnall {
407d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4087a984708SDavid Chisnall     RLock _(mut());
409d72607e9SDimitry Andric #endif
4107a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
4117a984708SDavid Chisnall     return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
4127a984708SDavid Chisnall }
4137a984708SDavid Chisnall 
4147a984708SDavid Chisnall bool
4154f7ab58eSDimitry Andric __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
4167a984708SDavid Chisnall {
417d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4187a984708SDavid Chisnall     RLock _(mut());
419d72607e9SDimitry Andric #endif
4207a984708SDavid Chisnall     __i_node* i = __find_iterator(__i);
4217a984708SDavid Chisnall     __i_node* j = __find_iterator(__j);
4227a984708SDavid Chisnall     __c_node* ci = i != nullptr ? i->__c_ : nullptr;
4237a984708SDavid Chisnall     __c_node* cj = j != nullptr ? j->__c_ : nullptr;
4247a984708SDavid Chisnall     return ci != nullptr && ci == cj;
4257a984708SDavid Chisnall }
4267a984708SDavid Chisnall 
4277a984708SDavid Chisnall void
4287a984708SDavid Chisnall __libcpp_db::swap(void* c1, void* c2)
4297a984708SDavid Chisnall {
430d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4317a984708SDavid Chisnall     WLock _(mut());
432d72607e9SDimitry Andric #endif
43394e3ee44SDavid Chisnall     size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
4347a984708SDavid Chisnall     __c_node* p1 = __cbeg_[hc];
4357a984708SDavid Chisnall     _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
4367a984708SDavid Chisnall     while (p1->__c_ != c1)
4377a984708SDavid Chisnall     {
4387a984708SDavid Chisnall         p1 = p1->__next_;
4397a984708SDavid Chisnall         _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
4407a984708SDavid Chisnall     }
44194e3ee44SDavid Chisnall     hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
4427a984708SDavid Chisnall     __c_node* p2 = __cbeg_[hc];
4437a984708SDavid Chisnall     _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
4447a984708SDavid Chisnall     while (p2->__c_ != c2)
4457a984708SDavid Chisnall     {
4467a984708SDavid Chisnall         p2 = p2->__next_;
4477a984708SDavid Chisnall         _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
4487a984708SDavid Chisnall     }
4497a984708SDavid Chisnall     std::swap(p1->beg_, p2->beg_);
4507a984708SDavid Chisnall     std::swap(p1->end_, p2->end_);
4517a984708SDavid Chisnall     std::swap(p1->cap_, p2->cap_);
4527a984708SDavid Chisnall     for (__i_node** p = p1->beg_; p != p1->end_; ++p)
4537a984708SDavid Chisnall         (*p)->__c_ = p1;
4547a984708SDavid Chisnall     for (__i_node** p = p2->beg_; p != p2->end_; ++p)
4557a984708SDavid Chisnall         (*p)->__c_ = p2;
4567a984708SDavid Chisnall }
4577a984708SDavid Chisnall 
4587a984708SDavid Chisnall void
4597a984708SDavid Chisnall __libcpp_db::__insert_i(void* __i)
4607a984708SDavid Chisnall {
461d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4627a984708SDavid Chisnall     WLock _(mut());
463d72607e9SDimitry Andric #endif
4647a984708SDavid Chisnall     __insert_iterator(__i);
4657a984708SDavid Chisnall }
4667a984708SDavid Chisnall 
4677a984708SDavid Chisnall void
4687a984708SDavid Chisnall __c_node::__add(__i_node* i)
4697a984708SDavid Chisnall {
4707a984708SDavid Chisnall     if (end_ == cap_)
4717a984708SDavid Chisnall     {
47294e3ee44SDavid Chisnall         size_t nc = 2*static_cast<size_t>(cap_ - beg_);
4737a984708SDavid Chisnall         if (nc == 0)
4747a984708SDavid Chisnall             nc = 1;
4754bab9fd9SDavid Chisnall         __i_node** beg =
4764bab9fd9SDavid Chisnall            static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
4777a984708SDavid Chisnall         if (beg == nullptr)
478936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
4797a984708SDavid Chisnall             throw bad_alloc();
480936e9439SDimitry Andric #else
481936e9439SDimitry Andric             abort();
482936e9439SDimitry Andric #endif
4837a984708SDavid Chisnall         if (nc > 1)
4847a984708SDavid Chisnall             memcpy(beg, beg_, nc/2*sizeof(__i_node*));
4857a984708SDavid Chisnall         free(beg_);
4867a984708SDavid Chisnall         beg_ = beg;
4877a984708SDavid Chisnall         end_ = beg_ + nc/2;
4887a984708SDavid Chisnall         cap_ = beg_ + nc;
4897a984708SDavid Chisnall     }
4907a984708SDavid Chisnall     *end_++ = i;
4917a984708SDavid Chisnall }
4927a984708SDavid Chisnall 
4937a984708SDavid Chisnall // private api
4947a984708SDavid Chisnall 
4957a984708SDavid Chisnall _LIBCPP_HIDDEN
4967a984708SDavid Chisnall __i_node*
4977a984708SDavid Chisnall __libcpp_db::__insert_iterator(void* __i)
4987a984708SDavid Chisnall {
49994e3ee44SDavid Chisnall     if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
5007a984708SDavid Chisnall     {
50194e3ee44SDavid Chisnall         size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
5024bab9fd9SDavid Chisnall         __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
5037a984708SDavid Chisnall         if (ibeg == nullptr)
504936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
5057a984708SDavid Chisnall             throw bad_alloc();
506936e9439SDimitry Andric #else
507936e9439SDimitry Andric             abort();
508936e9439SDimitry Andric #endif
5097a984708SDavid Chisnall         for (__i_node** p = __ibeg_; p != __iend_; ++p)
5107a984708SDavid Chisnall         {
5117a984708SDavid Chisnall             __i_node* q = *p;
5127a984708SDavid Chisnall             while (q != nullptr)
5137a984708SDavid Chisnall             {
5147a984708SDavid Chisnall                 size_t h = hash<void*>()(q->__i_) % nc;
5157a984708SDavid Chisnall                 __i_node* r = q->__next_;
5167a984708SDavid Chisnall                 q->__next_ = ibeg[h];
5177a984708SDavid Chisnall                 ibeg[h] = q;
5187a984708SDavid Chisnall                 q = r;
5197a984708SDavid Chisnall             }
5207a984708SDavid Chisnall         }
5217a984708SDavid Chisnall         free(__ibeg_);
5227a984708SDavid Chisnall         __ibeg_ = ibeg;
5237a984708SDavid Chisnall         __iend_ = __ibeg_ + nc;
5247a984708SDavid Chisnall     }
52594e3ee44SDavid Chisnall     size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
5267a984708SDavid Chisnall     __i_node* p = __ibeg_[hi];
5274bab9fd9SDavid Chisnall     __i_node* r = __ibeg_[hi] =
5284bab9fd9SDavid Chisnall       static_cast<__i_node*>(malloc(sizeof(__i_node)));
5297a984708SDavid Chisnall     if (r == nullptr)
530936e9439SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
5317a984708SDavid Chisnall         throw bad_alloc();
532936e9439SDimitry Andric #else
533936e9439SDimitry Andric         abort();
534936e9439SDimitry Andric #endif
5357a984708SDavid Chisnall     ::new(r) __i_node(__i, p, nullptr);
5367a984708SDavid Chisnall     ++__isz_;
5377a984708SDavid Chisnall     return r;
5387a984708SDavid Chisnall }
5397a984708SDavid Chisnall 
5407a984708SDavid Chisnall _LIBCPP_HIDDEN
5417a984708SDavid Chisnall __i_node*
5427a984708SDavid Chisnall __libcpp_db::__find_iterator(const void* __i) const
5437a984708SDavid Chisnall {
5447a984708SDavid Chisnall     __i_node* r = nullptr;
5457a984708SDavid Chisnall     if (__ibeg_ != __iend_)
5467a984708SDavid Chisnall     {
54794e3ee44SDavid Chisnall         size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
5487a984708SDavid Chisnall         for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
5497a984708SDavid Chisnall         {
5507a984708SDavid Chisnall             if (nd->__i_ == __i)
5517a984708SDavid Chisnall             {
5527a984708SDavid Chisnall                 r = nd;
5537a984708SDavid Chisnall                 break;
5547a984708SDavid Chisnall             }
5557a984708SDavid Chisnall         }
5567a984708SDavid Chisnall     }
5577a984708SDavid Chisnall     return r;
5587a984708SDavid Chisnall }
5597a984708SDavid Chisnall 
5607a984708SDavid Chisnall _LIBCPP_HIDDEN
5617a984708SDavid Chisnall void
5627a984708SDavid Chisnall __c_node::__remove(__i_node* p)
5637a984708SDavid Chisnall {
5647a984708SDavid Chisnall     __i_node** r = find(beg_, end_, p);
5657a984708SDavid Chisnall     _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
5667a984708SDavid Chisnall     if (--end_ != r)
56794e3ee44SDavid Chisnall         memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
5687a984708SDavid Chisnall }
5697a984708SDavid Chisnall 
5707a984708SDavid Chisnall _LIBCPP_END_NAMESPACE_STD
571