10b57cec5SDimitry Andric //===-------------------------- debug.cpp ---------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "__config"
100b57cec5SDimitry Andric #include "__debug"
110b57cec5SDimitry Andric #include "functional"
120b57cec5SDimitry Andric #include "algorithm"
130b57cec5SDimitry Andric #include "string"
140b57cec5SDimitry Andric #include "cstdio"
150b57cec5SDimitry Andric #include "__hash_table"
160b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
170b57cec5SDimitry Andric #include "mutex"
18480093f4SDimitry Andric #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
190b57cec5SDimitry Andric #pragma comment(lib, "pthread")
200b57cec5SDimitry Andric #endif
210b57cec5SDimitry Andric #endif
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
240b57cec5SDimitry Andric
what() const250b57cec5SDimitry Andric std::string __libcpp_debug_info::what() const {
260b57cec5SDimitry Andric string msg = __file_;
270b57cec5SDimitry Andric msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '";
280b57cec5SDimitry Andric msg += __pred_;
290b57cec5SDimitry Andric msg += "' failed. ";
300b57cec5SDimitry Andric msg += __msg_;
310b57cec5SDimitry Andric return msg;
320b57cec5SDimitry Andric }
__libcpp_abort_debug_function(__libcpp_debug_info const & info)330b57cec5SDimitry Andric _LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
340b57cec5SDimitry Andric std::fprintf(stderr, "%s\n", info.what().c_str());
350b57cec5SDimitry Andric std::abort();
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric _LIBCPP_SAFE_STATIC __libcpp_debug_function_type
390b57cec5SDimitry Andric __libcpp_debug_function = __libcpp_abort_debug_function;
400b57cec5SDimitry Andric
__libcpp_set_debug_function(__libcpp_debug_function_type __func)410b57cec5SDimitry Andric bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
420b57cec5SDimitry Andric __libcpp_debug_function = __func;
430b57cec5SDimitry Andric return true;
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric _LIBCPP_FUNC_VIS
470b57cec5SDimitry Andric __libcpp_db*
__get_db()480b57cec5SDimitry Andric __get_db()
490b57cec5SDimitry Andric {
500b57cec5SDimitry Andric static _LIBCPP_NO_DESTROY __libcpp_db db;
510b57cec5SDimitry Andric return &db;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric _LIBCPP_FUNC_VIS
550b57cec5SDimitry Andric const __libcpp_db*
__get_const_db()560b57cec5SDimitry Andric __get_const_db()
570b57cec5SDimitry Andric {
580b57cec5SDimitry Andric return __get_db();
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric namespace
620b57cec5SDimitry Andric {
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
650b57cec5SDimitry Andric typedef mutex mutex_type;
660b57cec5SDimitry Andric typedef lock_guard<mutex_type> WLock;
670b57cec5SDimitry Andric typedef lock_guard<mutex_type> RLock;
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric mutex_type&
mut()700b57cec5SDimitry Andric mut()
710b57cec5SDimitry Andric {
720b57cec5SDimitry Andric static _LIBCPP_NO_DESTROY mutex_type m;
730b57cec5SDimitry Andric return m;
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric #endif // !_LIBCPP_HAS_NO_THREADS
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric } // unnamed namespace
780b57cec5SDimitry Andric
~__i_node()790b57cec5SDimitry Andric __i_node::~__i_node()
800b57cec5SDimitry Andric {
810b57cec5SDimitry Andric if (__next_)
820b57cec5SDimitry Andric {
830b57cec5SDimitry Andric __next_->~__i_node();
840b57cec5SDimitry Andric free(__next_);
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric
~__c_node()880b57cec5SDimitry Andric __c_node::~__c_node()
890b57cec5SDimitry Andric {
900b57cec5SDimitry Andric free(beg_);
910b57cec5SDimitry Andric if (__next_)
920b57cec5SDimitry Andric {
930b57cec5SDimitry Andric __next_->~__c_node();
940b57cec5SDimitry Andric free(__next_);
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
__libcpp_db()980b57cec5SDimitry Andric __libcpp_db::__libcpp_db()
990b57cec5SDimitry Andric : __cbeg_(nullptr),
1000b57cec5SDimitry Andric __cend_(nullptr),
1010b57cec5SDimitry Andric __csz_(0),
1020b57cec5SDimitry Andric __ibeg_(nullptr),
1030b57cec5SDimitry Andric __iend_(nullptr),
1040b57cec5SDimitry Andric __isz_(0)
1050b57cec5SDimitry Andric {
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric
~__libcpp_db()1080b57cec5SDimitry Andric __libcpp_db::~__libcpp_db()
1090b57cec5SDimitry Andric {
1100b57cec5SDimitry Andric if (__cbeg_)
1110b57cec5SDimitry Andric {
1120b57cec5SDimitry Andric for (__c_node** p = __cbeg_; p != __cend_; ++p)
1130b57cec5SDimitry Andric {
1140b57cec5SDimitry Andric if (*p != nullptr)
1150b57cec5SDimitry Andric {
1160b57cec5SDimitry Andric (*p)->~__c_node();
1170b57cec5SDimitry Andric free(*p);
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric free(__cbeg_);
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric if (__ibeg_)
1230b57cec5SDimitry Andric {
1240b57cec5SDimitry Andric for (__i_node** p = __ibeg_; p != __iend_; ++p)
1250b57cec5SDimitry Andric {
1260b57cec5SDimitry Andric if (*p != nullptr)
1270b57cec5SDimitry Andric {
1280b57cec5SDimitry Andric (*p)->~__i_node();
1290b57cec5SDimitry Andric free(*p);
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric free(__ibeg_);
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric void*
__find_c_from_i(void * __i) const1370b57cec5SDimitry Andric __libcpp_db::__find_c_from_i(void* __i) const
1380b57cec5SDimitry Andric {
1390b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1400b57cec5SDimitry Andric RLock _(mut());
1410b57cec5SDimitry Andric #endif
1420b57cec5SDimitry Andric __i_node* i = __find_iterator(__i);
1430b57cec5SDimitry Andric _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
1440b57cec5SDimitry Andric return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric void
__insert_ic(void * __i,const void * __c)1480b57cec5SDimitry Andric __libcpp_db::__insert_ic(void* __i, const void* __c)
1490b57cec5SDimitry Andric {
1500b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1510b57cec5SDimitry Andric WLock _(mut());
1520b57cec5SDimitry Andric #endif
1530b57cec5SDimitry Andric if (__cbeg_ == __cend_)
1540b57cec5SDimitry Andric return;
1550b57cec5SDimitry Andric size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
1560b57cec5SDimitry Andric __c_node* c = __cbeg_[hc];
1570b57cec5SDimitry Andric if (c == nullptr)
1580b57cec5SDimitry Andric return;
1590b57cec5SDimitry Andric while (c->__c_ != __c)
1600b57cec5SDimitry Andric {
1610b57cec5SDimitry Andric c = c->__next_;
1620b57cec5SDimitry Andric if (c == nullptr)
1630b57cec5SDimitry Andric return;
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric __i_node* i = __insert_iterator(__i);
1660b57cec5SDimitry Andric c->__add(i);
1670b57cec5SDimitry Andric i->__c_ = c;
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric
1700b57cec5SDimitry Andric void
__insert_c(void * __c,__libcpp_db::_InsertConstruct * __fn)1710b57cec5SDimitry Andric __libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
1720b57cec5SDimitry Andric {
1730b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
1740b57cec5SDimitry Andric WLock _(mut());
1750b57cec5SDimitry Andric #endif
1760b57cec5SDimitry Andric if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
1770b57cec5SDimitry Andric {
1780b57cec5SDimitry Andric size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
1790b57cec5SDimitry Andric __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*)));
1800b57cec5SDimitry Andric if (cbeg == nullptr)
1810b57cec5SDimitry Andric __throw_bad_alloc();
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric for (__c_node** p = __cbeg_; p != __cend_; ++p)
1840b57cec5SDimitry Andric {
1850b57cec5SDimitry Andric __c_node* q = *p;
1860b57cec5SDimitry Andric while (q != nullptr)
1870b57cec5SDimitry Andric {
1880b57cec5SDimitry Andric size_t h = hash<void*>()(q->__c_) % nc;
1890b57cec5SDimitry Andric __c_node* r = q->__next_;
1900b57cec5SDimitry Andric q->__next_ = cbeg[h];
1910b57cec5SDimitry Andric cbeg[h] = q;
1920b57cec5SDimitry Andric q = r;
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric free(__cbeg_);
1960b57cec5SDimitry Andric __cbeg_ = cbeg;
1970b57cec5SDimitry Andric __cend_ = __cbeg_ + nc;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2000b57cec5SDimitry Andric __c_node* p = __cbeg_[hc];
2010b57cec5SDimitry Andric void *buf = malloc(sizeof(__c_node));
2020b57cec5SDimitry Andric if (buf == nullptr)
2030b57cec5SDimitry Andric __throw_bad_alloc();
2040b57cec5SDimitry Andric __cbeg_[hc] = __fn(buf, __c, p);
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric ++__csz_;
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
2090b57cec5SDimitry Andric void
__erase_i(void * __i)2100b57cec5SDimitry Andric __libcpp_db::__erase_i(void* __i)
2110b57cec5SDimitry Andric {
2120b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2130b57cec5SDimitry Andric WLock _(mut());
2140b57cec5SDimitry Andric #endif
2150b57cec5SDimitry Andric if (__ibeg_ != __iend_)
2160b57cec5SDimitry Andric {
2170b57cec5SDimitry Andric size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
2180b57cec5SDimitry Andric __i_node* p = __ibeg_[hi];
2190b57cec5SDimitry Andric if (p != nullptr)
2200b57cec5SDimitry Andric {
2210b57cec5SDimitry Andric __i_node* q = nullptr;
2220b57cec5SDimitry Andric while (p->__i_ != __i)
2230b57cec5SDimitry Andric {
2240b57cec5SDimitry Andric q = p;
2250b57cec5SDimitry Andric p = p->__next_;
2260b57cec5SDimitry Andric if (p == nullptr)
2270b57cec5SDimitry Andric return;
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric if (q == nullptr)
2300b57cec5SDimitry Andric __ibeg_[hi] = p->__next_;
2310b57cec5SDimitry Andric else
2320b57cec5SDimitry Andric q->__next_ = p->__next_;
2330b57cec5SDimitry Andric __c_node* c = p->__c_;
2340b57cec5SDimitry Andric --__isz_;
2350b57cec5SDimitry Andric if (c != nullptr)
2360b57cec5SDimitry Andric c->__remove(p);
2370b57cec5SDimitry Andric free(p);
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric void
__invalidate_all(void * __c)2430b57cec5SDimitry Andric __libcpp_db::__invalidate_all(void* __c)
2440b57cec5SDimitry Andric {
2450b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2460b57cec5SDimitry Andric WLock _(mut());
2470b57cec5SDimitry Andric #endif
2480b57cec5SDimitry Andric if (__cend_ != __cbeg_)
2490b57cec5SDimitry Andric {
2500b57cec5SDimitry Andric size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2510b57cec5SDimitry Andric __c_node* p = __cbeg_[hc];
2520b57cec5SDimitry Andric if (p == nullptr)
2530b57cec5SDimitry Andric return;
2540b57cec5SDimitry Andric while (p->__c_ != __c)
2550b57cec5SDimitry Andric {
2560b57cec5SDimitry Andric p = p->__next_;
2570b57cec5SDimitry Andric if (p == nullptr)
2580b57cec5SDimitry Andric return;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric while (p->end_ != p->beg_)
2610b57cec5SDimitry Andric {
2620b57cec5SDimitry Andric --p->end_;
2630b57cec5SDimitry Andric (*p->end_)->__c_ = nullptr;
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric __c_node*
__find_c_and_lock(void * __c) const2690b57cec5SDimitry Andric __libcpp_db::__find_c_and_lock(void* __c) const
2700b57cec5SDimitry Andric {
2710b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2720b57cec5SDimitry Andric mut().lock();
2730b57cec5SDimitry Andric #endif
2740b57cec5SDimitry Andric if (__cend_ == __cbeg_)
2750b57cec5SDimitry Andric {
2760b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2770b57cec5SDimitry Andric mut().unlock();
2780b57cec5SDimitry Andric #endif
2790b57cec5SDimitry Andric return nullptr;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
2820b57cec5SDimitry Andric __c_node* p = __cbeg_[hc];
2830b57cec5SDimitry Andric if (p == nullptr)
2840b57cec5SDimitry Andric {
2850b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2860b57cec5SDimitry Andric mut().unlock();
2870b57cec5SDimitry Andric #endif
2880b57cec5SDimitry Andric return nullptr;
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric while (p->__c_ != __c)
2910b57cec5SDimitry Andric {
2920b57cec5SDimitry Andric p = p->__next_;
2930b57cec5SDimitry Andric if (p == nullptr)
2940b57cec5SDimitry Andric {
2950b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
2960b57cec5SDimitry Andric mut().unlock();
2970b57cec5SDimitry Andric #endif
2980b57cec5SDimitry Andric return nullptr;
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric return p;
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andric __c_node*
__find_c(void * __c) const3050b57cec5SDimitry Andric __libcpp_db::__find_c(void* __c) const
3060b57cec5SDimitry Andric {
3070b57cec5SDimitry Andric size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
3080b57cec5SDimitry Andric __c_node* p = __cbeg_[hc];
3090b57cec5SDimitry Andric _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
3100b57cec5SDimitry Andric while (p->__c_ != __c)
3110b57cec5SDimitry Andric {
3120b57cec5SDimitry Andric p = p->__next_;
3130b57cec5SDimitry Andric _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric return p;
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andric void
unlock() const3190b57cec5SDimitry Andric __libcpp_db::unlock() const
3200b57cec5SDimitry Andric {
3210b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3220b57cec5SDimitry Andric mut().unlock();
3230b57cec5SDimitry Andric #endif
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric void
__erase_c(void * __c)3270b57cec5SDimitry Andric __libcpp_db::__erase_c(void* __c)
3280b57cec5SDimitry Andric {
3290b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3300b57cec5SDimitry Andric WLock _(mut());
3310b57cec5SDimitry Andric #endif
3320b57cec5SDimitry Andric if (__cend_ != __cbeg_)
3330b57cec5SDimitry Andric {
3340b57cec5SDimitry Andric size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
3350b57cec5SDimitry Andric __c_node* p = __cbeg_[hc];
3360b57cec5SDimitry Andric if (p == nullptr)
3370b57cec5SDimitry Andric return;
3380b57cec5SDimitry Andric __c_node* q = nullptr;
3390b57cec5SDimitry Andric _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
3400b57cec5SDimitry Andric while (p->__c_ != __c)
3410b57cec5SDimitry Andric {
3420b57cec5SDimitry Andric q = p;
3430b57cec5SDimitry Andric p = p->__next_;
3440b57cec5SDimitry Andric if (p == nullptr)
3450b57cec5SDimitry Andric return;
3460b57cec5SDimitry Andric _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric if (q == nullptr)
3490b57cec5SDimitry Andric __cbeg_[hc] = p->__next_;
3500b57cec5SDimitry Andric else
3510b57cec5SDimitry Andric q->__next_ = p->__next_;
3520b57cec5SDimitry Andric while (p->end_ != p->beg_)
3530b57cec5SDimitry Andric {
3540b57cec5SDimitry Andric --p->end_;
3550b57cec5SDimitry Andric (*p->end_)->__c_ = nullptr;
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric free(p->beg_);
3580b57cec5SDimitry Andric free(p);
3590b57cec5SDimitry Andric --__csz_;
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric void
__iterator_copy(void * __i,const void * __i0)3640b57cec5SDimitry Andric __libcpp_db::__iterator_copy(void* __i, const void* __i0)
3650b57cec5SDimitry Andric {
3660b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3670b57cec5SDimitry Andric WLock _(mut());
3680b57cec5SDimitry Andric #endif
3690b57cec5SDimitry Andric __i_node* i = __find_iterator(__i);
3700b57cec5SDimitry Andric __i_node* i0 = __find_iterator(__i0);
3710b57cec5SDimitry Andric __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
3720b57cec5SDimitry Andric if (i == nullptr && i0 != nullptr)
3730b57cec5SDimitry Andric i = __insert_iterator(__i);
3740b57cec5SDimitry Andric __c_node* c = i != nullptr ? i->__c_ : nullptr;
3750b57cec5SDimitry Andric if (c != c0)
3760b57cec5SDimitry Andric {
3770b57cec5SDimitry Andric if (c != nullptr)
3780b57cec5SDimitry Andric c->__remove(i);
3790b57cec5SDimitry Andric if (i != nullptr)
3800b57cec5SDimitry Andric {
3810b57cec5SDimitry Andric i->__c_ = nullptr;
3820b57cec5SDimitry Andric if (c0 != nullptr)
3830b57cec5SDimitry Andric {
3840b57cec5SDimitry Andric i->__c_ = c0;
3850b57cec5SDimitry Andric i->__c_->__add(i);
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric
3910b57cec5SDimitry Andric bool
__dereferenceable(const void * __i) const3920b57cec5SDimitry Andric __libcpp_db::__dereferenceable(const void* __i) const
3930b57cec5SDimitry Andric {
3940b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
3950b57cec5SDimitry Andric RLock _(mut());
3960b57cec5SDimitry Andric #endif
3970b57cec5SDimitry Andric __i_node* i = __find_iterator(__i);
3980b57cec5SDimitry Andric return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andric bool
__decrementable(const void * __i) const4020b57cec5SDimitry Andric __libcpp_db::__decrementable(const void* __i) const
4030b57cec5SDimitry Andric {
4040b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4050b57cec5SDimitry Andric RLock _(mut());
4060b57cec5SDimitry Andric #endif
4070b57cec5SDimitry Andric __i_node* i = __find_iterator(__i);
4080b57cec5SDimitry Andric return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric
4110b57cec5SDimitry Andric bool
__addable(const void * __i,ptrdiff_t __n) const4120b57cec5SDimitry Andric __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
4130b57cec5SDimitry Andric {
4140b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4150b57cec5SDimitry Andric RLock _(mut());
4160b57cec5SDimitry Andric #endif
4170b57cec5SDimitry Andric __i_node* i = __find_iterator(__i);
4180b57cec5SDimitry Andric return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
4190b57cec5SDimitry Andric }
4200b57cec5SDimitry Andric
4210b57cec5SDimitry Andric bool
__subscriptable(const void * __i,ptrdiff_t __n) const4220b57cec5SDimitry Andric __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
4230b57cec5SDimitry Andric {
4240b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4250b57cec5SDimitry Andric RLock _(mut());
4260b57cec5SDimitry Andric #endif
4270b57cec5SDimitry Andric __i_node* i = __find_iterator(__i);
4280b57cec5SDimitry Andric return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric
4310b57cec5SDimitry Andric bool
__less_than_comparable(const void * __i,const void * __j) const4320b57cec5SDimitry Andric __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
4330b57cec5SDimitry Andric {
4340b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4350b57cec5SDimitry Andric RLock _(mut());
4360b57cec5SDimitry Andric #endif
4370b57cec5SDimitry Andric __i_node* i = __find_iterator(__i);
4380b57cec5SDimitry Andric __i_node* j = __find_iterator(__j);
4390b57cec5SDimitry Andric __c_node* ci = i != nullptr ? i->__c_ : nullptr;
4400b57cec5SDimitry Andric __c_node* cj = j != nullptr ? j->__c_ : nullptr;
441*5f7ddb14SDimitry Andric return ci == cj;
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric void
swap(void * c1,void * c2)4450b57cec5SDimitry Andric __libcpp_db::swap(void* c1, void* c2)
4460b57cec5SDimitry Andric {
4470b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4480b57cec5SDimitry Andric WLock _(mut());
4490b57cec5SDimitry Andric #endif
4500b57cec5SDimitry Andric size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
4510b57cec5SDimitry Andric __c_node* p1 = __cbeg_[hc];
4520b57cec5SDimitry Andric _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
4530b57cec5SDimitry Andric while (p1->__c_ != c1)
4540b57cec5SDimitry Andric {
4550b57cec5SDimitry Andric p1 = p1->__next_;
4560b57cec5SDimitry Andric _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
4570b57cec5SDimitry Andric }
4580b57cec5SDimitry Andric hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
4590b57cec5SDimitry Andric __c_node* p2 = __cbeg_[hc];
4600b57cec5SDimitry Andric _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
4610b57cec5SDimitry Andric while (p2->__c_ != c2)
4620b57cec5SDimitry Andric {
4630b57cec5SDimitry Andric p2 = p2->__next_;
4640b57cec5SDimitry Andric _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric std::swap(p1->beg_, p2->beg_);
4670b57cec5SDimitry Andric std::swap(p1->end_, p2->end_);
4680b57cec5SDimitry Andric std::swap(p1->cap_, p2->cap_);
4690b57cec5SDimitry Andric for (__i_node** p = p1->beg_; p != p1->end_; ++p)
4700b57cec5SDimitry Andric (*p)->__c_ = p1;
4710b57cec5SDimitry Andric for (__i_node** p = p2->beg_; p != p2->end_; ++p)
4720b57cec5SDimitry Andric (*p)->__c_ = p2;
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric void
__insert_i(void * __i)4760b57cec5SDimitry Andric __libcpp_db::__insert_i(void* __i)
4770b57cec5SDimitry Andric {
4780b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
4790b57cec5SDimitry Andric WLock _(mut());
4800b57cec5SDimitry Andric #endif
4810b57cec5SDimitry Andric __insert_iterator(__i);
4820b57cec5SDimitry Andric }
4830b57cec5SDimitry Andric
4840b57cec5SDimitry Andric void
__add(__i_node * i)4850b57cec5SDimitry Andric __c_node::__add(__i_node* i)
4860b57cec5SDimitry Andric {
4870b57cec5SDimitry Andric if (end_ == cap_)
4880b57cec5SDimitry Andric {
4890b57cec5SDimitry Andric size_t nc = 2*static_cast<size_t>(cap_ - beg_);
4900b57cec5SDimitry Andric if (nc == 0)
4910b57cec5SDimitry Andric nc = 1;
4920b57cec5SDimitry Andric __i_node** beg =
4930b57cec5SDimitry Andric static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
4940b57cec5SDimitry Andric if (beg == nullptr)
4950b57cec5SDimitry Andric __throw_bad_alloc();
4960b57cec5SDimitry Andric
4970b57cec5SDimitry Andric if (nc > 1)
4980b57cec5SDimitry Andric memcpy(beg, beg_, nc/2*sizeof(__i_node*));
4990b57cec5SDimitry Andric free(beg_);
5000b57cec5SDimitry Andric beg_ = beg;
5010b57cec5SDimitry Andric end_ = beg_ + nc/2;
5020b57cec5SDimitry Andric cap_ = beg_ + nc;
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric *end_++ = i;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric
5070b57cec5SDimitry Andric // private api
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andric _LIBCPP_HIDDEN
5100b57cec5SDimitry Andric __i_node*
__insert_iterator(void * __i)5110b57cec5SDimitry Andric __libcpp_db::__insert_iterator(void* __i)
5120b57cec5SDimitry Andric {
5130b57cec5SDimitry Andric if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
5140b57cec5SDimitry Andric {
5150b57cec5SDimitry Andric size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
5160b57cec5SDimitry Andric __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*)));
5170b57cec5SDimitry Andric if (ibeg == nullptr)
5180b57cec5SDimitry Andric __throw_bad_alloc();
5190b57cec5SDimitry Andric
5200b57cec5SDimitry Andric for (__i_node** p = __ibeg_; p != __iend_; ++p)
5210b57cec5SDimitry Andric {
5220b57cec5SDimitry Andric __i_node* q = *p;
5230b57cec5SDimitry Andric while (q != nullptr)
5240b57cec5SDimitry Andric {
5250b57cec5SDimitry Andric size_t h = hash<void*>()(q->__i_) % nc;
5260b57cec5SDimitry Andric __i_node* r = q->__next_;
5270b57cec5SDimitry Andric q->__next_ = ibeg[h];
5280b57cec5SDimitry Andric ibeg[h] = q;
5290b57cec5SDimitry Andric q = r;
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric }
5320b57cec5SDimitry Andric free(__ibeg_);
5330b57cec5SDimitry Andric __ibeg_ = ibeg;
5340b57cec5SDimitry Andric __iend_ = __ibeg_ + nc;
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
5370b57cec5SDimitry Andric __i_node* p = __ibeg_[hi];
5380b57cec5SDimitry Andric __i_node* r = __ibeg_[hi] =
5390b57cec5SDimitry Andric static_cast<__i_node*>(malloc(sizeof(__i_node)));
5400b57cec5SDimitry Andric if (r == nullptr)
5410b57cec5SDimitry Andric __throw_bad_alloc();
5420b57cec5SDimitry Andric
5430b57cec5SDimitry Andric ::new(r) __i_node(__i, p, nullptr);
5440b57cec5SDimitry Andric ++__isz_;
5450b57cec5SDimitry Andric return r;
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric
5480b57cec5SDimitry Andric _LIBCPP_HIDDEN
5490b57cec5SDimitry Andric __i_node*
__find_iterator(const void * __i) const5500b57cec5SDimitry Andric __libcpp_db::__find_iterator(const void* __i) const
5510b57cec5SDimitry Andric {
5520b57cec5SDimitry Andric __i_node* r = nullptr;
5530b57cec5SDimitry Andric if (__ibeg_ != __iend_)
5540b57cec5SDimitry Andric {
5550b57cec5SDimitry Andric size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
5560b57cec5SDimitry Andric for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
5570b57cec5SDimitry Andric {
5580b57cec5SDimitry Andric if (nd->__i_ == __i)
5590b57cec5SDimitry Andric {
5600b57cec5SDimitry Andric r = nd;
5610b57cec5SDimitry Andric break;
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric return r;
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric _LIBCPP_HIDDEN
5690b57cec5SDimitry Andric void
__remove(__i_node * p)5700b57cec5SDimitry Andric __c_node::__remove(__i_node* p)
5710b57cec5SDimitry Andric {
5720b57cec5SDimitry Andric __i_node** r = find(beg_, end_, p);
5730b57cec5SDimitry Andric _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
5740b57cec5SDimitry Andric if (--end_ != r)
5750b57cec5SDimitry Andric memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric
5780b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
579