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