xref: /minix/external/bsd/libc++/dist/libcxx/src/debug.cpp (revision 0a6a1f1d)
14684ddb6SLionel Sambuc //===-------------------------- debug.cpp ---------------------------------===//
24684ddb6SLionel Sambuc //
34684ddb6SLionel Sambuc //                     The LLVM Compiler Infrastructure
44684ddb6SLionel Sambuc //
54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
74684ddb6SLionel Sambuc //
84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
94684ddb6SLionel Sambuc 
104684ddb6SLionel Sambuc #define _LIBCPP_DEBUG 1
114684ddb6SLionel Sambuc #include "__config"
124684ddb6SLionel Sambuc #include "__debug"
134684ddb6SLionel Sambuc #include "functional"
144684ddb6SLionel Sambuc #include "algorithm"
154684ddb6SLionel Sambuc #include "__hash_table"
164684ddb6SLionel Sambuc #include "mutex"
174684ddb6SLionel Sambuc 
184684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
194684ddb6SLionel Sambuc 
204684ddb6SLionel Sambuc _LIBCPP_FUNC_VIS
214684ddb6SLionel Sambuc __libcpp_db*
__get_db()224684ddb6SLionel Sambuc __get_db()
234684ddb6SLionel Sambuc {
244684ddb6SLionel Sambuc     static __libcpp_db db;
254684ddb6SLionel Sambuc     return &db;
264684ddb6SLionel Sambuc }
274684ddb6SLionel Sambuc 
284684ddb6SLionel Sambuc _LIBCPP_FUNC_VIS
294684ddb6SLionel Sambuc const __libcpp_db*
__get_const_db()304684ddb6SLionel Sambuc __get_const_db()
314684ddb6SLionel Sambuc {
324684ddb6SLionel Sambuc     return __get_db();
334684ddb6SLionel Sambuc }
344684ddb6SLionel Sambuc 
354684ddb6SLionel Sambuc namespace
364684ddb6SLionel Sambuc {
374684ddb6SLionel Sambuc 
38*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
394684ddb6SLionel Sambuc typedef mutex mutex_type;
404684ddb6SLionel Sambuc typedef lock_guard<mutex_type> WLock;
414684ddb6SLionel Sambuc typedef lock_guard<mutex_type> RLock;
424684ddb6SLionel Sambuc 
434684ddb6SLionel Sambuc mutex_type&
mut()444684ddb6SLionel Sambuc mut()
454684ddb6SLionel Sambuc {
464684ddb6SLionel Sambuc     static mutex_type m;
474684ddb6SLionel Sambuc     return m;
484684ddb6SLionel Sambuc }
49*0a6a1f1dSLionel Sambuc #endif // !_LIBCPP_HAS_NO_THREADS
504684ddb6SLionel Sambuc 
514684ddb6SLionel Sambuc }  // unnamed namespace
524684ddb6SLionel Sambuc 
~__i_node()534684ddb6SLionel Sambuc __i_node::~__i_node()
544684ddb6SLionel Sambuc {
554684ddb6SLionel Sambuc     if (__next_)
564684ddb6SLionel Sambuc     {
574684ddb6SLionel Sambuc         __next_->~__i_node();
584684ddb6SLionel Sambuc         free(__next_);
594684ddb6SLionel Sambuc     }
604684ddb6SLionel Sambuc }
614684ddb6SLionel Sambuc 
~__c_node()624684ddb6SLionel Sambuc __c_node::~__c_node()
634684ddb6SLionel Sambuc {
644684ddb6SLionel Sambuc     free(beg_);
654684ddb6SLionel Sambuc     if (__next_)
664684ddb6SLionel Sambuc     {
674684ddb6SLionel Sambuc         __next_->~__c_node();
684684ddb6SLionel Sambuc         free(__next_);
694684ddb6SLionel Sambuc     }
704684ddb6SLionel Sambuc }
714684ddb6SLionel Sambuc 
__libcpp_db()724684ddb6SLionel Sambuc __libcpp_db::__libcpp_db()
734684ddb6SLionel Sambuc     : __cbeg_(nullptr),
744684ddb6SLionel Sambuc       __cend_(nullptr),
754684ddb6SLionel Sambuc       __csz_(0),
764684ddb6SLionel Sambuc       __ibeg_(nullptr),
774684ddb6SLionel Sambuc       __iend_(nullptr),
784684ddb6SLionel Sambuc       __isz_(0)
794684ddb6SLionel Sambuc {
804684ddb6SLionel Sambuc }
814684ddb6SLionel Sambuc 
~__libcpp_db()824684ddb6SLionel Sambuc __libcpp_db::~__libcpp_db()
834684ddb6SLionel Sambuc {
844684ddb6SLionel Sambuc     if (__cbeg_)
854684ddb6SLionel Sambuc     {
864684ddb6SLionel Sambuc         for (__c_node** p = __cbeg_; p != __cend_; ++p)
874684ddb6SLionel Sambuc         {
884684ddb6SLionel Sambuc             if (*p != nullptr)
894684ddb6SLionel Sambuc             {
904684ddb6SLionel Sambuc                 (*p)->~__c_node();
914684ddb6SLionel Sambuc                 free(*p);
924684ddb6SLionel Sambuc             }
934684ddb6SLionel Sambuc         }
944684ddb6SLionel Sambuc         free(__cbeg_);
954684ddb6SLionel Sambuc     }
964684ddb6SLionel Sambuc     if (__ibeg_)
974684ddb6SLionel Sambuc     {
984684ddb6SLionel Sambuc         for (__i_node** p = __ibeg_; p != __iend_; ++p)
994684ddb6SLionel Sambuc         {
1004684ddb6SLionel Sambuc             if (*p != nullptr)
1014684ddb6SLionel Sambuc             {
1024684ddb6SLionel Sambuc                 (*p)->~__i_node();
1034684ddb6SLionel Sambuc                 free(*p);
1044684ddb6SLionel Sambuc             }
1054684ddb6SLionel Sambuc         }
1064684ddb6SLionel Sambuc         free(__ibeg_);
1074684ddb6SLionel Sambuc     }
1084684ddb6SLionel Sambuc }
1094684ddb6SLionel Sambuc 
1104684ddb6SLionel Sambuc void*
__find_c_from_i(void * __i) const1114684ddb6SLionel Sambuc __libcpp_db::__find_c_from_i(void* __i) const
1124684ddb6SLionel Sambuc {
113*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
1144684ddb6SLionel Sambuc     RLock _(mut());
115*0a6a1f1dSLionel Sambuc #endif
1164684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
1174684ddb6SLionel Sambuc     _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
1184684ddb6SLionel Sambuc     return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
1194684ddb6SLionel Sambuc }
1204684ddb6SLionel Sambuc 
1214684ddb6SLionel Sambuc void
__insert_ic(void * __i,const void * __c)1224684ddb6SLionel Sambuc __libcpp_db::__insert_ic(void* __i, const void* __c)
1234684ddb6SLionel Sambuc {
124*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
1254684ddb6SLionel Sambuc     WLock _(mut());
126*0a6a1f1dSLionel Sambuc #endif
1274684ddb6SLionel Sambuc     if (__cbeg_ == __cend_)
1284684ddb6SLionel Sambuc         return;
1294684ddb6SLionel Sambuc     size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
1304684ddb6SLionel Sambuc     __c_node* c = __cbeg_[hc];
1314684ddb6SLionel Sambuc     if (c == nullptr)
1324684ddb6SLionel Sambuc         return;
1334684ddb6SLionel Sambuc     while (c->__c_ != __c)
1344684ddb6SLionel Sambuc     {
1354684ddb6SLionel Sambuc         c = c->__next_;
1364684ddb6SLionel Sambuc         if (c == nullptr)
1374684ddb6SLionel Sambuc             return;
1384684ddb6SLionel Sambuc     }
1394684ddb6SLionel Sambuc     __i_node* i = __insert_iterator(__i);
1404684ddb6SLionel Sambuc     c->__add(i);
1414684ddb6SLionel Sambuc     i->__c_ = c;
1424684ddb6SLionel Sambuc }
1434684ddb6SLionel Sambuc 
1444684ddb6SLionel Sambuc __c_node*
__insert_c(void * __c)1454684ddb6SLionel Sambuc __libcpp_db::__insert_c(void* __c)
1464684ddb6SLionel Sambuc {
147*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
1484684ddb6SLionel Sambuc     WLock _(mut());
149*0a6a1f1dSLionel Sambuc #endif
1504684ddb6SLionel Sambuc     if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
1514684ddb6SLionel Sambuc     {
1524684ddb6SLionel Sambuc         size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
1534684ddb6SLionel Sambuc         __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
1544684ddb6SLionel Sambuc         if (cbeg == nullptr)
1554684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
1564684ddb6SLionel Sambuc             throw bad_alloc();
1574684ddb6SLionel Sambuc #else
1584684ddb6SLionel Sambuc             abort();
1594684ddb6SLionel Sambuc #endif
1604684ddb6SLionel Sambuc         for (__c_node** p = __cbeg_; p != __cend_; ++p)
1614684ddb6SLionel Sambuc         {
1624684ddb6SLionel Sambuc             __c_node* q = *p;
1634684ddb6SLionel Sambuc             while (q != nullptr)
1644684ddb6SLionel Sambuc             {
1654684ddb6SLionel Sambuc                 size_t h = hash<void*>()(q->__c_) % nc;
1664684ddb6SLionel Sambuc                 __c_node* r = q->__next_;
1674684ddb6SLionel Sambuc                 q->__next_ = cbeg[h];
1684684ddb6SLionel Sambuc                 cbeg[h] = q;
1694684ddb6SLionel Sambuc                 q = r;
1704684ddb6SLionel Sambuc             }
1714684ddb6SLionel Sambuc         }
1724684ddb6SLionel Sambuc         free(__cbeg_);
1734684ddb6SLionel Sambuc         __cbeg_ = cbeg;
1744684ddb6SLionel Sambuc         __cend_ = __cbeg_ + nc;
1754684ddb6SLionel Sambuc     }
1764684ddb6SLionel Sambuc     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
1774684ddb6SLionel Sambuc     __c_node* p = __cbeg_[hc];
1784684ddb6SLionel Sambuc     __c_node* r = __cbeg_[hc] =
1794684ddb6SLionel Sambuc       static_cast<__c_node*>(malloc(sizeof(__c_node)));
1804684ddb6SLionel Sambuc     if (__cbeg_[hc] == nullptr)
1814684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
1824684ddb6SLionel Sambuc         throw bad_alloc();
1834684ddb6SLionel Sambuc #else
1844684ddb6SLionel Sambuc         abort();
1854684ddb6SLionel Sambuc #endif
1864684ddb6SLionel Sambuc     r->__c_ = __c;
1874684ddb6SLionel Sambuc     r->__next_ = p;
1884684ddb6SLionel Sambuc     ++__csz_;
1894684ddb6SLionel Sambuc     return r;
1904684ddb6SLionel Sambuc }
1914684ddb6SLionel Sambuc 
1924684ddb6SLionel Sambuc void
__erase_i(void * __i)1934684ddb6SLionel Sambuc __libcpp_db::__erase_i(void* __i)
1944684ddb6SLionel Sambuc {
195*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
1964684ddb6SLionel Sambuc     WLock _(mut());
197*0a6a1f1dSLionel Sambuc #endif
1984684ddb6SLionel Sambuc     if (__ibeg_ != __iend_)
1994684ddb6SLionel Sambuc     {
2004684ddb6SLionel Sambuc         size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
2014684ddb6SLionel Sambuc         __i_node* p = __ibeg_[hi];
2024684ddb6SLionel Sambuc         if (p != nullptr)
2034684ddb6SLionel Sambuc         {
2044684ddb6SLionel Sambuc             __i_node* q = nullptr;
2054684ddb6SLionel Sambuc             while (p->__i_ != __i)
2064684ddb6SLionel Sambuc             {
2074684ddb6SLionel Sambuc                 q = p;
2084684ddb6SLionel Sambuc                 p = p->__next_;
2094684ddb6SLionel Sambuc                 if (p == nullptr)
2104684ddb6SLionel Sambuc                     return;
2114684ddb6SLionel Sambuc             }
2124684ddb6SLionel Sambuc             if (q == nullptr)
2134684ddb6SLionel Sambuc                 __ibeg_[hi] = p->__next_;
2144684ddb6SLionel Sambuc             else
2154684ddb6SLionel Sambuc                 q->__next_ = p->__next_;
2164684ddb6SLionel Sambuc             __c_node* c = p->__c_;
2174684ddb6SLionel Sambuc             --__isz_;
2184684ddb6SLionel Sambuc             if (c != nullptr)
2194684ddb6SLionel Sambuc                 c->__remove(p);
220*0a6a1f1dSLionel Sambuc             free(p);
2214684ddb6SLionel Sambuc         }
2224684ddb6SLionel Sambuc     }
2234684ddb6SLionel Sambuc }
2244684ddb6SLionel Sambuc 
2254684ddb6SLionel Sambuc void
__invalidate_all(void * __c)2264684ddb6SLionel Sambuc __libcpp_db::__invalidate_all(void* __c)
2274684ddb6SLionel Sambuc {
228*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
2294684ddb6SLionel Sambuc     WLock _(mut());
230*0a6a1f1dSLionel Sambuc #endif
2314684ddb6SLionel Sambuc     if (__cend_ != __cbeg_)
2324684ddb6SLionel Sambuc     {
2334684ddb6SLionel Sambuc         size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2344684ddb6SLionel Sambuc         __c_node* p = __cbeg_[hc];
2354684ddb6SLionel Sambuc         if (p == nullptr)
2364684ddb6SLionel Sambuc             return;
2374684ddb6SLionel Sambuc         while (p->__c_ != __c)
2384684ddb6SLionel Sambuc         {
2394684ddb6SLionel Sambuc             p = p->__next_;
2404684ddb6SLionel Sambuc             if (p == nullptr)
2414684ddb6SLionel Sambuc                 return;
2424684ddb6SLionel Sambuc         }
2434684ddb6SLionel Sambuc         while (p->end_ != p->beg_)
2444684ddb6SLionel Sambuc         {
2454684ddb6SLionel Sambuc             --p->end_;
2464684ddb6SLionel Sambuc             (*p->end_)->__c_ = nullptr;
2474684ddb6SLionel Sambuc         }
2484684ddb6SLionel Sambuc     }
2494684ddb6SLionel Sambuc }
2504684ddb6SLionel Sambuc 
2514684ddb6SLionel Sambuc __c_node*
__find_c_and_lock(void * __c) const2524684ddb6SLionel Sambuc __libcpp_db::__find_c_and_lock(void* __c) const
2534684ddb6SLionel Sambuc {
254*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
2554684ddb6SLionel Sambuc     mut().lock();
256*0a6a1f1dSLionel Sambuc #endif
2574684ddb6SLionel Sambuc     if (__cend_ == __cbeg_)
2584684ddb6SLionel Sambuc     {
259*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
2604684ddb6SLionel Sambuc         mut().unlock();
261*0a6a1f1dSLionel Sambuc #endif
2624684ddb6SLionel Sambuc         return nullptr;
2634684ddb6SLionel Sambuc     }
2644684ddb6SLionel Sambuc     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2654684ddb6SLionel Sambuc     __c_node* p = __cbeg_[hc];
2664684ddb6SLionel Sambuc     if (p == nullptr)
2674684ddb6SLionel Sambuc     {
268*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
2694684ddb6SLionel Sambuc         mut().unlock();
270*0a6a1f1dSLionel Sambuc #endif
2714684ddb6SLionel Sambuc         return nullptr;
2724684ddb6SLionel Sambuc     }
2734684ddb6SLionel Sambuc     while (p->__c_ != __c)
2744684ddb6SLionel Sambuc     {
2754684ddb6SLionel Sambuc         p = p->__next_;
2764684ddb6SLionel Sambuc         if (p == nullptr)
2774684ddb6SLionel Sambuc         {
278*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
2794684ddb6SLionel Sambuc             mut().unlock();
280*0a6a1f1dSLionel Sambuc #endif
2814684ddb6SLionel Sambuc             return nullptr;
2824684ddb6SLionel Sambuc         }
2834684ddb6SLionel Sambuc     }
2844684ddb6SLionel Sambuc     return p;
2854684ddb6SLionel Sambuc }
2864684ddb6SLionel Sambuc 
2874684ddb6SLionel Sambuc __c_node*
__find_c(void * __c) const2884684ddb6SLionel Sambuc __libcpp_db::__find_c(void* __c) const
2894684ddb6SLionel Sambuc {
2904684ddb6SLionel Sambuc     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2914684ddb6SLionel Sambuc     __c_node* p = __cbeg_[hc];
2924684ddb6SLionel Sambuc     _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
2934684ddb6SLionel Sambuc     while (p->__c_ != __c)
2944684ddb6SLionel Sambuc     {
2954684ddb6SLionel Sambuc         p = p->__next_;
2964684ddb6SLionel Sambuc         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
2974684ddb6SLionel Sambuc     }
2984684ddb6SLionel Sambuc     return p;
2994684ddb6SLionel Sambuc }
3004684ddb6SLionel Sambuc 
3014684ddb6SLionel Sambuc void
unlock() const3024684ddb6SLionel Sambuc __libcpp_db::unlock() const
3034684ddb6SLionel Sambuc {
304*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
3054684ddb6SLionel Sambuc     mut().unlock();
306*0a6a1f1dSLionel Sambuc #endif
3074684ddb6SLionel Sambuc }
3084684ddb6SLionel Sambuc 
3094684ddb6SLionel Sambuc void
__erase_c(void * __c)3104684ddb6SLionel Sambuc __libcpp_db::__erase_c(void* __c)
3114684ddb6SLionel Sambuc {
312*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
3134684ddb6SLionel Sambuc     WLock _(mut());
314*0a6a1f1dSLionel Sambuc #endif
3154684ddb6SLionel Sambuc     if (__cend_ != __cbeg_)
3164684ddb6SLionel Sambuc     {
3174684ddb6SLionel Sambuc         size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
3184684ddb6SLionel Sambuc         __c_node* p = __cbeg_[hc];
3194684ddb6SLionel Sambuc         if (p == nullptr)
3204684ddb6SLionel Sambuc             return;
3214684ddb6SLionel Sambuc         __c_node* q = nullptr;
3224684ddb6SLionel Sambuc         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
3234684ddb6SLionel Sambuc         while (p->__c_ != __c)
3244684ddb6SLionel Sambuc         {
3254684ddb6SLionel Sambuc             q = p;
3264684ddb6SLionel Sambuc             p = p->__next_;
3274684ddb6SLionel Sambuc             if (p == nullptr)
3284684ddb6SLionel Sambuc                 return;
3294684ddb6SLionel Sambuc             _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
3304684ddb6SLionel Sambuc         }
3314684ddb6SLionel Sambuc         if (q == nullptr)
3324684ddb6SLionel Sambuc             __cbeg_[hc] = p->__next_;
3334684ddb6SLionel Sambuc         else
3344684ddb6SLionel Sambuc             q->__next_ = p->__next_;
3354684ddb6SLionel Sambuc         while (p->end_ != p->beg_)
3364684ddb6SLionel Sambuc         {
3374684ddb6SLionel Sambuc             --p->end_;
3384684ddb6SLionel Sambuc             (*p->end_)->__c_ = nullptr;
3394684ddb6SLionel Sambuc         }
3404684ddb6SLionel Sambuc         free(p->beg_);
3414684ddb6SLionel Sambuc         free(p);
3424684ddb6SLionel Sambuc         --__csz_;
3434684ddb6SLionel Sambuc     }
3444684ddb6SLionel Sambuc }
3454684ddb6SLionel Sambuc 
3464684ddb6SLionel Sambuc void
__iterator_copy(void * __i,const void * __i0)3474684ddb6SLionel Sambuc __libcpp_db::__iterator_copy(void* __i, const void* __i0)
3484684ddb6SLionel Sambuc {
349*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
3504684ddb6SLionel Sambuc     WLock _(mut());
351*0a6a1f1dSLionel Sambuc #endif
3524684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
3534684ddb6SLionel Sambuc     __i_node* i0 = __find_iterator(__i0);
3544684ddb6SLionel Sambuc     __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
3554684ddb6SLionel Sambuc     if (i == nullptr && i0 != nullptr)
3564684ddb6SLionel Sambuc         i = __insert_iterator(__i);
3574684ddb6SLionel Sambuc     __c_node* c = i != nullptr ? i->__c_ : nullptr;
3584684ddb6SLionel Sambuc     if (c != c0)
3594684ddb6SLionel Sambuc     {
3604684ddb6SLionel Sambuc         if (c != nullptr)
3614684ddb6SLionel Sambuc             c->__remove(i);
3624684ddb6SLionel Sambuc         if (i != nullptr)
3634684ddb6SLionel Sambuc         {
3644684ddb6SLionel Sambuc             i->__c_ = nullptr;
3654684ddb6SLionel Sambuc             if (c0 != nullptr)
3664684ddb6SLionel Sambuc             {
3674684ddb6SLionel Sambuc                 i->__c_ = c0;
3684684ddb6SLionel Sambuc                 i->__c_->__add(i);
3694684ddb6SLionel Sambuc             }
3704684ddb6SLionel Sambuc         }
3714684ddb6SLionel Sambuc     }
3724684ddb6SLionel Sambuc }
3734684ddb6SLionel Sambuc 
3744684ddb6SLionel Sambuc bool
__dereferenceable(const void * __i) const3754684ddb6SLionel Sambuc __libcpp_db::__dereferenceable(const void* __i) const
3764684ddb6SLionel Sambuc {
377*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
3784684ddb6SLionel Sambuc     RLock _(mut());
379*0a6a1f1dSLionel Sambuc #endif
3804684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
3814684ddb6SLionel Sambuc     return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
3824684ddb6SLionel Sambuc }
3834684ddb6SLionel Sambuc 
3844684ddb6SLionel Sambuc bool
__decrementable(const void * __i) const3854684ddb6SLionel Sambuc __libcpp_db::__decrementable(const void* __i) const
3864684ddb6SLionel Sambuc {
387*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
3884684ddb6SLionel Sambuc     RLock _(mut());
389*0a6a1f1dSLionel Sambuc #endif
3904684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
3914684ddb6SLionel Sambuc     return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
3924684ddb6SLionel Sambuc }
3934684ddb6SLionel Sambuc 
3944684ddb6SLionel Sambuc bool
__addable(const void * __i,ptrdiff_t __n) const3954684ddb6SLionel Sambuc __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
3964684ddb6SLionel Sambuc {
397*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
3984684ddb6SLionel Sambuc     RLock _(mut());
399*0a6a1f1dSLionel Sambuc #endif
4004684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
4014684ddb6SLionel Sambuc     return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
4024684ddb6SLionel Sambuc }
4034684ddb6SLionel Sambuc 
4044684ddb6SLionel Sambuc bool
__subscriptable(const void * __i,ptrdiff_t __n) const4054684ddb6SLionel Sambuc __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
4064684ddb6SLionel Sambuc {
407*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
4084684ddb6SLionel Sambuc     RLock _(mut());
409*0a6a1f1dSLionel Sambuc #endif
4104684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
4114684ddb6SLionel Sambuc     return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
4124684ddb6SLionel Sambuc }
4134684ddb6SLionel Sambuc 
4144684ddb6SLionel Sambuc bool
__less_than_comparable(const void * __i,const void * __j) const4154684ddb6SLionel Sambuc __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
4164684ddb6SLionel Sambuc {
417*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
4184684ddb6SLionel Sambuc     RLock _(mut());
419*0a6a1f1dSLionel Sambuc #endif
4204684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
4214684ddb6SLionel Sambuc     __i_node* j = __find_iterator(__j);
4224684ddb6SLionel Sambuc     __c_node* ci = i != nullptr ? i->__c_ : nullptr;
4234684ddb6SLionel Sambuc     __c_node* cj = j != nullptr ? j->__c_ : nullptr;
4244684ddb6SLionel Sambuc     return ci != nullptr && ci == cj;
4254684ddb6SLionel Sambuc }
4264684ddb6SLionel Sambuc 
4274684ddb6SLionel Sambuc void
swap(void * c1,void * c2)4284684ddb6SLionel Sambuc __libcpp_db::swap(void* c1, void* c2)
4294684ddb6SLionel Sambuc {
430*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
4314684ddb6SLionel Sambuc     WLock _(mut());
432*0a6a1f1dSLionel Sambuc #endif
4334684ddb6SLionel Sambuc     size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
4344684ddb6SLionel Sambuc     __c_node* p1 = __cbeg_[hc];
4354684ddb6SLionel Sambuc     _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
4364684ddb6SLionel Sambuc     while (p1->__c_ != c1)
4374684ddb6SLionel Sambuc     {
4384684ddb6SLionel Sambuc         p1 = p1->__next_;
4394684ddb6SLionel Sambuc         _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
4404684ddb6SLionel Sambuc     }
4414684ddb6SLionel Sambuc     hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
4424684ddb6SLionel Sambuc     __c_node* p2 = __cbeg_[hc];
4434684ddb6SLionel Sambuc     _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
4444684ddb6SLionel Sambuc     while (p2->__c_ != c2)
4454684ddb6SLionel Sambuc     {
4464684ddb6SLionel Sambuc         p2 = p2->__next_;
4474684ddb6SLionel Sambuc         _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
4484684ddb6SLionel Sambuc     }
4494684ddb6SLionel Sambuc     std::swap(p1->beg_, p2->beg_);
4504684ddb6SLionel Sambuc     std::swap(p1->end_, p2->end_);
4514684ddb6SLionel Sambuc     std::swap(p1->cap_, p2->cap_);
4524684ddb6SLionel Sambuc     for (__i_node** p = p1->beg_; p != p1->end_; ++p)
4534684ddb6SLionel Sambuc         (*p)->__c_ = p1;
4544684ddb6SLionel Sambuc     for (__i_node** p = p2->beg_; p != p2->end_; ++p)
4554684ddb6SLionel Sambuc         (*p)->__c_ = p2;
4564684ddb6SLionel Sambuc }
4574684ddb6SLionel Sambuc 
4584684ddb6SLionel Sambuc void
__insert_i(void * __i)4594684ddb6SLionel Sambuc __libcpp_db::__insert_i(void* __i)
4604684ddb6SLionel Sambuc {
461*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
4624684ddb6SLionel Sambuc     WLock _(mut());
463*0a6a1f1dSLionel Sambuc #endif
4644684ddb6SLionel Sambuc     __insert_iterator(__i);
4654684ddb6SLionel Sambuc }
4664684ddb6SLionel Sambuc 
4674684ddb6SLionel Sambuc void
__add(__i_node * i)4684684ddb6SLionel Sambuc __c_node::__add(__i_node* i)
4694684ddb6SLionel Sambuc {
4704684ddb6SLionel Sambuc     if (end_ == cap_)
4714684ddb6SLionel Sambuc     {
4724684ddb6SLionel Sambuc         size_t nc = 2*static_cast<size_t>(cap_ - beg_);
4734684ddb6SLionel Sambuc         if (nc == 0)
4744684ddb6SLionel Sambuc             nc = 1;
4754684ddb6SLionel Sambuc         __i_node** beg =
4764684ddb6SLionel Sambuc            static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
4774684ddb6SLionel Sambuc         if (beg == nullptr)
4784684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
4794684ddb6SLionel Sambuc             throw bad_alloc();
4804684ddb6SLionel Sambuc #else
4814684ddb6SLionel Sambuc             abort();
4824684ddb6SLionel Sambuc #endif
4834684ddb6SLionel Sambuc         if (nc > 1)
4844684ddb6SLionel Sambuc             memcpy(beg, beg_, nc/2*sizeof(__i_node*));
4854684ddb6SLionel Sambuc         free(beg_);
4864684ddb6SLionel Sambuc         beg_ = beg;
4874684ddb6SLionel Sambuc         end_ = beg_ + nc/2;
4884684ddb6SLionel Sambuc         cap_ = beg_ + nc;
4894684ddb6SLionel Sambuc     }
4904684ddb6SLionel Sambuc     *end_++ = i;
4914684ddb6SLionel Sambuc }
4924684ddb6SLionel Sambuc 
4934684ddb6SLionel Sambuc // private api
4944684ddb6SLionel Sambuc 
4954684ddb6SLionel Sambuc _LIBCPP_HIDDEN
4964684ddb6SLionel Sambuc __i_node*
__insert_iterator(void * __i)4974684ddb6SLionel Sambuc __libcpp_db::__insert_iterator(void* __i)
4984684ddb6SLionel Sambuc {
4994684ddb6SLionel Sambuc     if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
5004684ddb6SLionel Sambuc     {
5014684ddb6SLionel Sambuc         size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
5024684ddb6SLionel Sambuc         __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
5034684ddb6SLionel Sambuc         if (ibeg == nullptr)
5044684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
5054684ddb6SLionel Sambuc             throw bad_alloc();
5064684ddb6SLionel Sambuc #else
5074684ddb6SLionel Sambuc             abort();
5084684ddb6SLionel Sambuc #endif
5094684ddb6SLionel Sambuc         for (__i_node** p = __ibeg_; p != __iend_; ++p)
5104684ddb6SLionel Sambuc         {
5114684ddb6SLionel Sambuc             __i_node* q = *p;
5124684ddb6SLionel Sambuc             while (q != nullptr)
5134684ddb6SLionel Sambuc             {
5144684ddb6SLionel Sambuc                 size_t h = hash<void*>()(q->__i_) % nc;
5154684ddb6SLionel Sambuc                 __i_node* r = q->__next_;
5164684ddb6SLionel Sambuc                 q->__next_ = ibeg[h];
5174684ddb6SLionel Sambuc                 ibeg[h] = q;
5184684ddb6SLionel Sambuc                 q = r;
5194684ddb6SLionel Sambuc             }
5204684ddb6SLionel Sambuc         }
5214684ddb6SLionel Sambuc         free(__ibeg_);
5224684ddb6SLionel Sambuc         __ibeg_ = ibeg;
5234684ddb6SLionel Sambuc         __iend_ = __ibeg_ + nc;
5244684ddb6SLionel Sambuc     }
5254684ddb6SLionel Sambuc     size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
5264684ddb6SLionel Sambuc     __i_node* p = __ibeg_[hi];
5274684ddb6SLionel Sambuc     __i_node* r = __ibeg_[hi] =
5284684ddb6SLionel Sambuc       static_cast<__i_node*>(malloc(sizeof(__i_node)));
5294684ddb6SLionel Sambuc     if (r == nullptr)
5304684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
5314684ddb6SLionel Sambuc         throw bad_alloc();
5324684ddb6SLionel Sambuc #else
5334684ddb6SLionel Sambuc         abort();
5344684ddb6SLionel Sambuc #endif
5354684ddb6SLionel Sambuc     ::new(r) __i_node(__i, p, nullptr);
5364684ddb6SLionel Sambuc     ++__isz_;
5374684ddb6SLionel Sambuc     return r;
5384684ddb6SLionel Sambuc }
5394684ddb6SLionel Sambuc 
5404684ddb6SLionel Sambuc _LIBCPP_HIDDEN
5414684ddb6SLionel Sambuc __i_node*
__find_iterator(const void * __i) const5424684ddb6SLionel Sambuc __libcpp_db::__find_iterator(const void* __i) const
5434684ddb6SLionel Sambuc {
5444684ddb6SLionel Sambuc     __i_node* r = nullptr;
5454684ddb6SLionel Sambuc     if (__ibeg_ != __iend_)
5464684ddb6SLionel Sambuc     {
5474684ddb6SLionel Sambuc         size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
5484684ddb6SLionel Sambuc         for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
5494684ddb6SLionel Sambuc         {
5504684ddb6SLionel Sambuc             if (nd->__i_ == __i)
5514684ddb6SLionel Sambuc             {
5524684ddb6SLionel Sambuc                 r = nd;
5534684ddb6SLionel Sambuc                 break;
5544684ddb6SLionel Sambuc             }
5554684ddb6SLionel Sambuc         }
5564684ddb6SLionel Sambuc     }
5574684ddb6SLionel Sambuc     return r;
5584684ddb6SLionel Sambuc }
5594684ddb6SLionel Sambuc 
5604684ddb6SLionel Sambuc _LIBCPP_HIDDEN
5614684ddb6SLionel Sambuc void
__remove(__i_node * p)5624684ddb6SLionel Sambuc __c_node::__remove(__i_node* p)
5634684ddb6SLionel Sambuc {
5644684ddb6SLionel Sambuc     __i_node** r = find(beg_, end_, p);
5654684ddb6SLionel Sambuc     _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
5664684ddb6SLionel Sambuc     if (--end_ != r)
5674684ddb6SLionel Sambuc         memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
5684684ddb6SLionel Sambuc }
5694684ddb6SLionel Sambuc 
5704684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
571